From 37c3d8ffb74ee6622cd2ddbc31701bc0a0ec2128 Mon Sep 17 00:00:00 2001 From: Radek Davidek Date: Tue, 19 May 2026 19:42:21 +0200 Subject: [PATCH] some fixes and optimizations --- pgo-automat-settings.properties | 20 +- pom.xml | 7 - src/main/java/com/pokemongo/GlobalHotkey.java | 28 +-- .../com/pokemongo/PokemonGoAutomation.java | 226 +++++++++--------- src/main/java/com/pokemongo/PokemonGoGUI.java | 206 ++++++++-------- .../java/com/pokemongo/PositionPicker.java | 102 -------- src/main/java/com/pokemongo/WindowFinder.java | 80 +++---- 7 files changed, 276 insertions(+), 393 deletions(-) delete mode 100644 src/main/java/com/pokemongo/PositionPicker.java diff --git a/pgo-automat-settings.properties b/pgo-automat-settings.properties index db01edb..f7db455 100644 --- a/pgo-automat-settings.properties +++ b/pgo-automat-settings.properties @@ -1,13 +1,13 @@ -#Pokmon GO Automatizace - Nastaven -#Fri Jan 23 16:03:46 CET 2026 +#Pokmon GO Automation - Settings +#Tue May 19 19:39:52 CEST 2026 autoklik.count=1000 -window.width=807 -transfer.delay=0 -autoklik.x=2123 -window.height=743 autoklik.downArrow=true -autoklik.y=1129 autoklik.interval=150 -transfer.count=6 -window.x=887 -window.y=505 +autoklik.x=2123 +autoklik.y=1129 +transfer.count=60 +transfer.delay=0 +window.height=743 +window.width=412 +window.x=1546 +window.y=343 diff --git a/pom.xml b/pom.xml index 6b15510..a4985cf 100644 --- a/pom.xml +++ b/pom.xml @@ -33,13 +33,6 @@ 1.18.26 provided - - - - org.openpnp - opencv - 4.7.0-0 - diff --git a/src/main/java/com/pokemongo/GlobalHotkey.java b/src/main/java/com/pokemongo/GlobalHotkey.java index 30c62a8..dcfcf35 100644 --- a/src/main/java/com/pokemongo/GlobalHotkey.java +++ b/src/main/java/com/pokemongo/GlobalHotkey.java @@ -7,11 +7,10 @@ import java.util.Set; import javax.swing.JLabel; /** - * Globální hotkey listener pro detekci CTRL+ALT+Q. - * Na Linuxu funguje i bez fokusu přes nativní polling X11. + * Global hotkey listener for detecting CTRL+ALT+Q. + * On Linux works without focus via native X11 polling. */ public class GlobalHotkey extends JLabel { - private static GlobalHotkey instance; private static final long HOTKEY_COOLDOWN_MS = 700; private final GlobalKeyListener globalKeyListener; @@ -24,11 +23,11 @@ public class GlobalHotkey extends JLabel { this.onHotkey = onHotkey; this.globalKeyListener = new GlobalKeyListener(); - // Registrace globálního key listeneru pro případy, kdy má aplikace fokus + // Register global key listener for cases when application has focus KeyboardFocusManager.getCurrentKeyboardFocusManager() .addKeyEventDispatcher(globalKeyListener); - // Nativní polling globální hotkey na Linuxu (funguje i bez fokusu) + // Native polling of global hotkey on Linux (works without focus) if (isLinux()) { pollingThread = new Thread(() -> { while (running && !Thread.currentThread().isInterrupted()) { @@ -40,7 +39,7 @@ public class GlobalHotkey extends JLabel { boolean qPressed = WindowFinder.isKeyPressedGlobally(0x71) || WindowFinder.isKeyPressedGlobally(0x51); if (ctrl && alt && qPressed) { - triggerHotkey("Globální NATIVNÍ hotkey detekován: CTRL+ALT+Q"); + triggerHotkey("Global NATIVE hotkey detected: CTRL+ALT+Q"); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); @@ -55,16 +54,9 @@ public class GlobalHotkey extends JLabel { } } - public static GlobalHotkey create(Runnable onHotkey) { - if (instance == null) { - instance = new GlobalHotkey(onHotkey); - } - return instance; - } - public boolean isKeyPressed(int keyCode) { - // Na Linuxu pro šipky používáme výhradně nativní globální detekci. - // Standardní KeyEventDispatcher se může "zaseknout", pokud okno ztratí fokus během stisku. + // On Linux for arrows we use exclusively native global detection. + // Standard KeyEventDispatcher may get "stuck" if window loses focus during press. if (isLinux()) { if (keyCode == KeyEvent.VK_DOWN) { try { @@ -108,7 +100,7 @@ public class GlobalHotkey extends JLabel { } /** - * Interní třída pro globální naslouchání na klávesnici + * Internal class for global keyboard listening */ private class GlobalKeyListener implements java.awt.KeyEventDispatcher { private Set pressedKeys = new HashSet<>(); @@ -125,14 +117,14 @@ public class GlobalHotkey extends JLabel { // Detekce CTRL+ALT+Q if (e.getKeyCode() == KeyEvent.VK_Q && e.isControlDown() && e.isAltDown()) { - triggerHotkey("Globální hotkey detekován: CTRL+ALT+Q"); + triggerHotkey("Global hotkey detected: CTRL+ALT+Q"); return true; // Konzumovat event } } else if (e.getID() == KeyEvent.KEY_RELEASED) { pressedKeys.remove(e.getKeyCode()); } - return false; // Nepropagovat ostatní eventy + return false; // Do not propagate other events } } } diff --git a/src/main/java/com/pokemongo/PokemonGoAutomation.java b/src/main/java/com/pokemongo/PokemonGoAutomation.java index 2dd2d21..260b48c 100644 --- a/src/main/java/com/pokemongo/PokemonGoAutomation.java +++ b/src/main/java/com/pokemongo/PokemonGoAutomation.java @@ -15,8 +15,8 @@ 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. + * Automation tool for Pokémon GO. + * Finds running application, selects all Pokémon and clicks Transfer button. */ public class PokemonGoAutomation { @@ -29,8 +29,8 @@ public class PokemonGoAutomation { private BufferedImage includeTemplate; // Include button template private static final int DELAY_BETWEEN_CLICKS = 100; // ms private static final int DELAY_AFTER_ACTION = 100; // ms - private int transferredPokemonCount = 0; // Počet transfernutých pokémonů - private Point initialMousePosition = null; // Pozice kurzoru před začátkem automatizace + private int transferredPokemonCount = 0; // Count of transferred pokemon + private Point initialMousePosition = null; // Cursor position before start of automation private volatile boolean stopRequested = false; public PokemonGoAutomation() throws AWTException { @@ -41,14 +41,14 @@ public class PokemonGoAutomation { } /** - * Vrátí počet dosud transfernutých pokémonů + * Returns count of pokemon transferred so far */ public int getTransferredCount() { return transferredPokemonCount; } /** - * Resetuje počítadlo transfernutých pokémonů + * Resets counter of transferred pokemon */ public void resetTransferredCount() { transferredPokemonCount = 0; @@ -63,62 +63,62 @@ public class PokemonGoAutomation { } /** - * Pořídí screenshot oblasti okna + * Takes screenshot of window area */ private BufferedImage captureScreen(Rectangle area) { return robot.createScreenCapture(area); } /** - * Načte templaty pro tlačítka TRANSFER (t1.png) a confirmation (t2.png) + * Loads templates for TRANSFER button (t1.png) and 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); + System.out.println("✅ Template TRANSFER loaded from: " + t1Paths); String t2Paths = "/t2.png"; t2Template = ImageIO.read(getClass().getResourceAsStream(t2Paths)); - System.out.println("✅ Template Potvrzení načten z: " + t2Paths); + System.out.println("✅ Template Confirmation loaded from: " + t2Paths); String t3Paths = "/t3.png"; t3Template = ImageIO.read(getClass().getResourceAsStream(t3Paths)); - System.out.println("✅ Template Potvrzení načten z: " + t3Paths); + System.out.println("✅ Template Confirmation loaded from: " + t3Paths); String pok1Paths = "/pok1.png"; pok1Template = ImageIO.read(getClass().getResourceAsStream(pok1Paths)); - System.out.println("✅ Template Pokémon načten z: " + pok1Paths); + System.out.println("✅ Template Pokémon loaded from: " + pok1Paths); String includePaths = "/include.png"; includeTemplate = ImageIO.read(getClass().getResourceAsStream(includePaths)); - System.out.println("✅ Template INCLUDE načten z: " + includePaths); + System.out.println("✅ Template INCLUDE loaded from: " + includePaths); if (t1Template == null) { - System.out.println("⚠️ Template t1.png nebyl nalezen"); + System.out.println("⚠️ Template t1.png not found"); } if (t2Template == null) { - System.out.println("⚠️ Template t2.png nebyl nalezen"); + System.out.println("⚠️ Template t2.png not found"); } if (pok1Template == null) { - System.out.println("⚠️ Template pok1.png nebyl nalezen"); + System.out.println("⚠️ Template pok1.png not found"); } if (includeTemplate == null) { - System.out.println("⚠️ Template include.png nebyl nalezen"); + System.out.println("⚠️ Template include.png not found"); } } catch (IOException e) { - System.err.println("⚠️ Chyba při načítání templates: " + e.getMessage()); + System.err.println("⚠️ Error loading templates: " + e.getMessage()); } } /** - * Porovnává template s oblastí v obrázku - jednoduché pixelové porovnání s - * optimalizací + * Compares template with area in image - simple pixel comparison with + * optimization */ private double templateMatch(BufferedImage screenshot, int startX, int startY, BufferedImage template, int tolerance) { @@ -152,7 +152,7 @@ public class PokemonGoAutomation { int templateRGB = template.getRGB(x, y); int screenRGB = screenshot.getRGB(startX + x, startY + y); - // Rozdělit RGB hodnoty + // Split RGB values int tR = (templateRGB >> 16) & 0xFF; int tG = (templateRGB >> 8) & 0xFF; int tB = templateRGB & 0xFF; @@ -161,7 +161,7 @@ public class PokemonGoAutomation { int sG = (screenRGB >> 8) & 0xFF; int sB = screenRGB & 0xFF; - // Porovnat barvy - zvýšená tolerance pro lepší detekci + // Compare colors - increased tolerance for better detection int rDiff = Math.abs(tR - sR); int gDiff = Math.abs(tG - sG); int bDiff = Math.abs(tB - sB); @@ -169,7 +169,7 @@ public class PokemonGoAutomation { if (rDiff < tolerance && gDiff < tolerance && bDiff < tolerance) { matchingPixels++; - // Early exit - pokud jsme nedosáhli minima, skončit + // Early exit - if we have not reached minimum, stop if (matchingPixels < requiredMatch / 2 && (y * tWidth + x) > (totalPixels / 2)) { return 0.0; } @@ -177,15 +177,15 @@ public class PokemonGoAutomation { } } - // Vrátit procentuální shodu (0.0-1.0) + // Return percentage match (0.0-1.0) return (double) matchingPixels / totalPixels; } /** - * Najde a vrátí pozici potvrzovacího tlačítka bez kliknutí + * Finds and returns position of confirmation button without clicking */ private Point findConfirmTransferButtonPosition(BufferedImage template, int tolerance) { - System.out.println("Hledám potvrzovací TRANSFER tlačítko pomocí template matchingu..."); + System.out.println("Looking for confirm TRANSFER button using template matching..."); if (shouldStop()) { return null; @@ -196,7 +196,7 @@ public class PokemonGoAutomation { int tWidth = template.getWidth(); int tHeight = template.getHeight(); - // Dialog je obvykle v horní polovině po TRANSFER kliknutí + // Dialog is usually in upper half after TRANSFER click int searchStartY = (int) (windowBounds.height * 0.40); int searchEndY = (int) (windowBounds.height * 0.75); @@ -204,12 +204,12 @@ public class PokemonGoAutomation { int bestX = 0; int bestY = 0; - // Skenovat Y-ové pozice s větším krokem - 15px místo 5px pro zrychlení + // Scan Y positions with larger step - 15px instead of 5px for speed for (int y = searchStartY; y <= searchEndY - tHeight; y += 15) { if (shouldStop()) { return null; } - // Skenovat také X pozice pro nalezení středu shody + // Also scan X positions to find center of match for (int x = 0; x <= windowBounds.width - tWidth; x += 30) { double score = templateMatch(screenshot, x, y, template, tolerance); @@ -225,17 +225,17 @@ public class PokemonGoAutomation { 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: " + System.out.println("✅ Found confirmation button (template match) at: " + bestMatch + " (match: " + String.format("%.1f", bestScore * 100) + "%)"); return bestMatch; } - System.out.println("Template nenalezen"); + System.out.println("Template not found"); return null; } private Point findIncludeButtonPosition(int tolerance) { - System.out.println("Hledám tlačítko INCLUDE pomocí template matchingu (include.png)..."); + System.out.println("Looking for INCLUDE button using template matching (include.png)..."); if (shouldStop()) { return null; @@ -246,7 +246,7 @@ public class PokemonGoAutomation { int tWidth = includeTemplate.getWidth(); int tHeight = includeTemplate.getHeight(); - // Dialog je obvykle v horní polovině po TRANSFER kliknutí + // Dialog is usually in upper half after TRANSFER click int searchStartY = (int) (windowBounds.height * 0.40); int searchEndY = (int) (windowBounds.height * 0.75); @@ -254,12 +254,12 @@ public class PokemonGoAutomation { int bestX = 0; int bestY = 0; - // Skenovat Y-ové pozice s větším krokem - 15px místo 5px pro zrychlení + // Scan Y positions with larger step - 15px instead of 5px for speed for (int y = searchStartY; y <= searchEndY - tHeight; y += 15) { if (shouldStop()) { return null; } - // Skenovat také X pozice pro nalezení středu shody + // Also scan X positions to find center of match for (int x = 0; x <= windowBounds.width - tWidth; x += 30) { double score = templateMatch(screenshot, x, y, includeTemplate, tolerance); @@ -275,17 +275,17 @@ public class PokemonGoAutomation { 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: " + System.out.println("✅ Found INCLUDE button (template match) at: " + bestMatch + " (match: " + String.format("%.1f", bestScore * 100) + "%)"); return bestMatch; } - System.out.println("Template nenalezen"); + System.out.println("Template not found"); return null; } /** - * Najde okno s názvem obsahujícím "Pokémon" nebo "Pokemon" + * Finds window with name containing "Pokémon" or "Pokemon" */ public boolean findPokemonGoWindow() { try { @@ -293,15 +293,15 @@ public class PokemonGoAutomation { if (bounds != null && bounds.width > 0 && bounds.height > 0) { windowBounds = bounds; - System.out.println("Nalezeno okno: " + windowBounds); + System.out.println("Window found: " + windowBounds); return true; } - System.out.println("Okno Pokémon GO nebylo nalezeno."); + System.out.println("Pokémon GO window not found."); return false; } catch (Exception e) { - System.err.println("Chyba při hledání okna: " + e.getMessage()); + System.err.println("Error finding window: " + e.getMessage()); e.printStackTrace(); return false; } @@ -312,12 +312,12 @@ public class PokemonGoAutomation { */ public void activateWindow() { try { - // Kliknutí na horní panel okna (title bar) pro aktivaci - // Title bar je obvykle 30-40px vysoký v horní části okna + // Click on top panel of window (title bar) for activation + // Title bar is usually 30-40px high at top of window int centerX = windowBounds.x + windowBounds.width / 2; - int titleBarY = windowBounds.y - 15; // 15px od vrcholu okna = horní panel + int titleBarY = windowBounds.y - 15; // 15px from top of window = top panel - System.out.println("Aktivuji okno kliknutím na title bar: (" + centerX + ", " + titleBarY + ")"); + System.out.println("Activating window by clicking title bar: (" + centerX + ", " + titleBarY + ")"); robot.mouseMove(centerX, titleBarY); robot.delay(200); @@ -325,26 +325,26 @@ public class PokemonGoAutomation { robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); robot.delay(DELAY_AFTER_ACTION); - System.out.println("Okno aktivováno"); + System.out.println("Window activated"); } catch (Exception e) { - System.err.println("Chyba při aktivaci okna: " + e.getMessage()); + System.err.println("Error activating window: " + e.getMessage()); } } /** - * Stiskne tlačítko Transfer na spodní části obrazovky + * Clicks Transfer button at bottom of screen */ public void clickTransferButton() { if (shouldStop()) { return; } - // Použít detekci tlačítka + // Use button detection // Point buttonPos = findTransferButtonPosition(); Point buttonPos = getAbsolutePoint(300, 1156); if (buttonPos == null) { - System.err.println("Tlačítko TRANSFER nebylo nalezeno!"); + System.err.println("TRANSFER button not found!"); return; } @@ -354,26 +354,26 @@ public class PokemonGoAutomation { robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); - System.out.println("Tlačítko TRANSFER stisknuto!"); + System.out.println("TRANSFER button clicked!"); robot.delay(DELAY_AFTER_ACTION); } /** - * Potvrdí transfer (pokud je potřeba potvrzovací dialog) + * Confirms transfer (if confirmation dialog is needed) */ public void clickConfirmTransferButton(BufferedImage template, int tolerance) { - System.out.println("Potvrzuji transfer - hledám confirmation button..."); + System.out.println("Confirming transfer - looking for confirmation button..."); if (shouldStop()) { return; } - robot.delay(100); // Počkat na zobrazení dialogu + robot.delay(100); // Wait for dialog to appear - // Najít zelené TRANSFER tlačítko v potvrzovacím dialogu + // Find green TRANSFER button in confirmation dialog Point buttonPos = findConfirmTransferButtonPosition(template, tolerance); if (buttonPos == null) { - System.out.println("Potvrzovací tlačítko nebylo nalezeno, přeskočím potvrzení."); + System.out.println("Confirmation button not found, skipping confirmation."); return; } @@ -383,23 +383,23 @@ public class PokemonGoAutomation { robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); - System.out.println("Transfer finálně potvrzen!"); + System.out.println("Transfer finally confirmed!"); robot.delay(DELAY_AFTER_ACTION); } public boolean clickIncludeButton(int tolerance) { - System.out.println("Potvrzuji transfer - hledám include.png (confirmation button)..."); + System.out.println("Confirming transfer - looking for include.png (confirmation button)..."); if (shouldStop()) { return false; } - robot.delay(100); // Počkat na zobrazení dialogu + robot.delay(100); // Wait for dialog to appear - // Najít zelené INCLUDE tlačítko v potvrzovacím dialogu + // Find green INCLUDE button in confirmation dialog Point buttonPos = findIncludeButtonPosition(tolerance); if (buttonPos == null) { - System.out.println("INCLUDE tlačítko nebylo nalezeno, přeskočím potvrzení."); + System.out.println("INCLUDE button not found, skipping confirmation."); return false; } @@ -409,79 +409,79 @@ public class PokemonGoAutomation { robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); - System.out.println("Transfer finálně potvrzen!"); + System.out.println("Transfer finally confirmed!"); robot.delay(DELAY_AFTER_ACTION); return true; } /** - * Spustí Transfer automatizaci s konkrétním počtem pokémonů + * Starts Transfer automation with specific number of pokemon * - * @param totalPokemonCount Celkový počet pokémonů k transferu - * @param delaySeconds Čekání mezi iteracemi (v sekundách) + * @param totalPokemonCount Total number of pokemon to transfer + * @param delaySeconds Delay between iterations (in seconds) */ public void runWithCount(int totalPokemonCount, int delaySeconds) { - System.out.println("Spouštím Transfer automatizaci - Počet pokémonů: " + totalPokemonCount + ", Čekání: " + System.out.println("Starting Transfer automation - Pokémon count: " + totalPokemonCount + ", Delay: " + delaySeconds + "s"); - // Uložit aktuální pozici kurzoru + // Save current cursor position PointerInfo pointerInfo = MouseInfo.getPointerInfo(); initialMousePosition = pointerInfo != null ? pointerInfo.getLocation() : null; if (initialMousePosition != null) { - System.out.println("Uložena počáteční pozice kurzoru: " + initialMousePosition); + System.out.println("Initial cursor position saved: " + initialMousePosition); } if (!findPokemonGoWindow()) { - System.err.println("Nepodařilo se najít okno Pokémon GO!"); + System.err.println("Failed to find Pokémon GO window!"); return; } activateWindow(); - System.out.println("Čekám 1 sekundu před začátkem..."); + System.out.println("Waiting 1 second before start..."); robot.delay(1000); int transferredCount = 0; - // Transferovat dokud nedosáhneme požadovaného počtu + // Transfer until we reach desired count try { while (transferredCount < totalPokemonCount) { - // Kontrola přerušení + // Check interruption if (shouldStop()) { - System.out.println("\n⚠️ Automatizace byla přerušena!"); + System.out.println("\n⚠️ Automation was interrupted!"); return; } int pokemonThisRound = Math.min(12, totalPokemonCount - transferredCount); System.out.println( - "\n=== Iterace " + (transferredCount / 9 + 1) + " - Transferuji maximálně " + pokemonThisRound - + " pokémonů ==="); + "\n=== Iteration " + (transferredCount / 9 + 1) + " - Transferring max " + pokemonThisRound + + " pokemon ==="); - // Vybrat pokémony a získat skutečný počet vybraných + // Select pokemon and get actual number selected int actualTransferredCount = selectAllPokemonCount(pokemonThisRound); if (shouldStop()) { - System.out.println("\n⚠️ Automatizace byla přerušena během označování!"); + System.out.println("\n⚠️ Automation was interrupted during selection!"); return; } - System.out.println("Čekám na TRANSFER..."); + System.out.println("Waiting for TRANSFER..."); clickTransferButton(); if (shouldStop()) { - System.out.println("\n⚠️ Automatizace byla přerušena po kliknutí na TRANSFER!"); + System.out.println("\n⚠️ Automation was interrupted after clicking TRANSFER!"); return; } - System.out.println("Čekám na INCLUDE dialog..."); + System.out.println("Waiting for INCLUDE dialog..."); robot.delay(100); if (clickIncludeButton(110)) { - System.out.println("Čekám na potvrzovací dialog t3..."); + System.out.println("Waiting for confirmation dialog t3..."); robot.delay(100); clickConfirmTransferButton(t3Template, 70); } else { - System.out.println("Čekám na potvrzovací dialog t2..."); + System.out.println("Waiting for confirmation dialog t2..."); robot.delay(100); clickConfirmTransferButton(t2Template, 70); } @@ -489,17 +489,17 @@ public class PokemonGoAutomation { transferredCount += actualTransferredCount; transferredPokemonCount += actualTransferredCount; - System.out.println("Transferováno v této iteraci: " + actualTransferredCount + " pokémonů (celkem: " + System.out.println("Transferred in this iteration: " + actualTransferredCount + "pokemon (total: " + transferredCount + ")"); - // Pokud ještě zbývá co transferovat, počkat + // If there is still something to transfer, wait if (transferredCount < totalPokemonCount) { - System.out.println("Přestávka: " + delaySeconds + " sekund..."); - // Čekat s kontrolou přerušení + System.out.println("Break: " + delaySeconds + " seconds..."); + // Wait with checking interruption long endTime = System.currentTimeMillis() + (delaySeconds * 1000L); while (System.currentTimeMillis() < endTime) { if (shouldStop()) { - System.out.println("\n⚠️ Automatizace byla přerušena během přestávky!"); + System.out.println("\n⚠️ Automation was interrupted during break!"); break; } robot.delay(100); @@ -511,48 +511,48 @@ public class PokemonGoAutomation { if (initialMousePosition != null) { try { robot.mouseMove(initialMousePosition.x, initialMousePosition.y); - System.out.println("Kurzor vrácen na počáteční pozici: " + initialMousePosition); + System.out.println("Cursor returned to initial position: " + initialMousePosition); } catch (Exception e) { - System.err.println("Chyba při obnovení pozice kurzoru: " + e.getMessage()); + System.err.println("Error restoring cursor position: " + e.getMessage()); } } } - System.out.println("\n✅ Transfer automatizace dokončena! Transferováno: " + transferredCount + " pokémonů"); + System.out.println("\n✅ Transfer automation complete! Transferred: " + transferredCount + "pokemon"); } /** - * Označí konkrétní počet pokémonů + * Selects specific number of pokemon * - * @return Skutečný počet vybraných pokémonů + * @return Actual number of selected pokemon */ private int selectAllPokemonCount(int count) { - System.out.println("Začínám označovat " + count + " pokémonů (pouze template matching)..."); + System.out.println("Starting to select " + count + "pokemon (template matching only)..."); List positions = getPossitionsAbsolute(); int maxPokemon = Math.min(count, positions.size()); - System.out.println("Budu označovat " + maxPokemon + " pokémonů..."); + System.out.println("Will select " + maxPokemon + "pokemon..."); for (int i = 0; i < maxPokemon; i++) { if (shouldStop()) { - System.out.println("Označování přerušeno."); + System.out.println("Selection interrupted."); return i; } Point pos = positions.get(i); - System.out.println("Klikám na Pokémona " + (i + 1) + "/" + maxPokemon + " na pozici: " + pos); + System.out.println("Clicking on Pokémon " + (i + 1) + "/" + maxPokemon + " at position: " + pos); robot.mouseMove(pos.x, pos.y); if (i == 0) { - System.out.println(" -> Dlouhé podržení (aktivace multi-select)"); + System.out.println(" -> Long press (activate multi-select)"); robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); robot.delay(700); robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); robot.delay(DELAY_AFTER_ACTION); } else { - System.out.println(" -> Normální klik"); + System.out.println(" -> Normal click"); robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); } @@ -560,8 +560,8 @@ public class PokemonGoAutomation { robot.delay(DELAY_BETWEEN_CLICKS); } - System.out.println("Označeno " + maxPokemon + " pokémonů!"); - System.out.println("Čekám před kliknutím na TRANSFER..."); + System.out.println("Selected " + maxPokemon + "pokemon!"); + System.out.println("Waiting before clicking TRANSFER..."); robot.delay(800); return maxPokemon; @@ -589,11 +589,11 @@ public class PokemonGoAutomation { } /** - * Převede relativní pozici v okně (0.0-1.0) na absolutní souřadnice obrazovky + * Converts relative position in window (0.0-1.0) to absolute screen coordinates * - * @param relativeX Relativní X pozice (0.0 = levý okraj, 1.0 = pravý okraj) - * @param relativeY Relativní Y pozice (0.0 = horní okraj, 1.0 = dolní okraj) - * @return Absolutní pozice na obrazovce + * @param relativeX Relative X position (0.0 = left edge, 1.0 = right edge) + * @param relativeY Relative Y position (0.0 = top edge, 1.0 = bottom edge) + * @return Absolute position on screen */ private Point getAbsolutePoint(int relativeX, int relativeY) { int xCorrection = 0; @@ -604,14 +604,14 @@ public class PokemonGoAutomation { } /** - * Vyčistí všechny prostředky používané automatizací - * Volat po skončení automatizace + * Cleans up all resources used by automation + * Call after automation finishes */ public void cleanup() { try { - System.out.println("Čištění prostředků automatizace..."); + System.out.println("Cleaning up automation resources..."); - // Uvolnit reference na obrázky + // Release references to images t1Template = null; t2Template = null; t3Template = null; @@ -619,16 +619,16 @@ public class PokemonGoAutomation { includeTemplate = null; windowBounds = null; - // Explicitně vyvolat garbage collector + // Explicitly invoke garbage collector System.gc(); - System.out.println("Prostředky automatizace vyčištěny"); + System.out.println("Automation resources cleaned"); } catch (Exception e) { - System.err.println("Chyba při čištění prostředků: " + e.getMessage()); + System.err.println("Error cleaning up resources: " + e.getMessage()); } } 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á..."); + System.out.println("=== Pokémon GO Automation Tool ==="); + System.out.println("Make sure Pokémon GO is running..."); } } diff --git a/src/main/java/com/pokemongo/PokemonGoGUI.java b/src/main/java/com/pokemongo/PokemonGoGUI.java index 8be51de..7335e4f 100644 --- a/src/main/java/com/pokemongo/PokemonGoGUI.java +++ b/src/main/java/com/pokemongo/PokemonGoGUI.java @@ -11,8 +11,8 @@ import java.io.*; import java.util.Properties; /** - * Jednoduchá GUI aplikace pro Pokémon GO automatizaci - * S kartami pro jednotlivé automatizace + * Simple GUI application for Pokémon GO automation + * With cards for individual automations */ public class PokemonGoGUI extends JFrame { @@ -23,7 +23,7 @@ public class PokemonGoGUI extends JFrame { private volatile boolean shouldStop = false; private PokemonGoAutomation automation; private Thread automationThread; - private int totalTransferredCount = 0; // Celkový počet transfernutých pokémonů + private int totalTransferredCount = 0; // Total count of transferred pokemon private volatile boolean autoClickRunning = false; private GlobalHotkey globalHotkey; @@ -49,13 +49,13 @@ public class PokemonGoGUI extends JFrame { private static final int CARD_MAX_WIDTH = 760; public PokemonGoGUI() { - setTitle("Pokémon GO Automatizace v" + VERSION); + setTitle("Pokémon GO Automation v" + VERSION); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - // Načtení uložených nastavení + // Load saved settings loadSettings(); - // Obnovení velikosti a pozice okna + // Restore window size and position 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")); @@ -72,7 +72,7 @@ public class PokemonGoGUI extends JFrame { setResizable(true); setBackground(PANEL_BACKGROUND); - // Uložení nastavení při zavření okna + // Save settings on window close addWindowListener(new java.awt.event.WindowAdapter() { @Override public void windowClosing(WindowEvent e) { @@ -80,24 +80,24 @@ public class PokemonGoGUI extends JFrame { } }); - // Hlavní panel + // Main 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:"); + // Top panel with status + JLabel stateLabel = new JLabel("Status:"); stateLabel.setFont(HEADER_FONT); stateLabel.setForeground(new Color(70, 70, 70)); - statusLabel = new JLabel("Připraven k spuštění"); + statusLabel = new JLabel("Ready to start"); statusLabel.setFont(BODY_FONT); statusLabel.setForeground(STATUS_DEFAULT); - JLabel versionLabel = new JLabel("verze " + VERSION); + JLabel versionLabel = new JLabel("v" + VERSION); versionLabel.setFont(SMALL_FONT); versionLabel.setForeground(new Color(120, 120, 120)); - stopButton = new JButton("⏹ ZASTAVIT (CTRL+ALT+Q)"); - stopButton.setPreferredSize(new Dimension(150, 30)); + stopButton = new JButton("⏹ STOP (CTRL+ALT+Q)"); + stopButton.setPreferredSize(new Dimension(220, 30)); styleButton(stopButton, PRIMARY_RED, Color.WHITE, SMALL_FONT); stopButton.setEnabled(false); stopButton.addActionListener(new ActionListener() { @@ -111,7 +111,7 @@ public class PokemonGoGUI extends JFrame { stopPanel.setOpaque(false); stopPanel.add(stopButton); - JLabel titleLabel = new JLabel("Pokémon GO Automatizace"); + JLabel titleLabel = new JLabel("Pokémon GO Automation"); titleLabel.setFont(TITLE_FONT); titleLabel.setForeground(new Color(30, 30, 30)); @@ -133,7 +133,7 @@ public class PokemonGoGUI extends JFrame { headerPanel.add(Box.createVerticalStrut(6)); headerPanel.add(statusRow); - // Panel s kartami automatizací + // Panel with automation cards JPanel cardsContainer = new JPanel(new GridBagLayout()); cardsContainer.setBackground(PANEL_BACKGROUND); cardsContainer.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8)); @@ -145,14 +145,14 @@ public class PokemonGoGUI extends JFrame { gbc.anchor = GridBagConstraints.NORTH; gbc.insets = new Insets(0, 0, 12, 0); - // Karta 1: Transfer automatizace + // Card 1: Transfer automation JPanel transferCard = createAutomationCard( - "🔄 TRANSFER AUTOMATIZACE", - "Hledá Pokémony, označí je a stiskne Transfer", + "🔄 TRANSFER AUTOMATION", + "Finds Pokémon, selects them, and clicks Transfer", null ); - // Najít START tlačítko - je v EAST pozici BorderLayoutu + // Find START button - in EAST position of BorderLayout JButton startBtnTransfer = findStartButton(transferCard); if (startBtnTransfer != null) { @@ -169,14 +169,14 @@ public class PokemonGoGUI extends JFrame { gbc.gridy++; gbc.insets = new Insets(0, 0, 12, 0); - // Karta 2: Autoklik + // Card 2: Autoclick JPanel autoClickCard = createAutomationCard( - "🖱️ AUTOKLIK", - "Automaticky klikuje na zadanou pozici", + "🖱️ AUTOCLICK", + "Automatically clicks at a given position", null ); - // Najít START tlačítko + // Find START button JButton startBtnAutoClick = findStartButton(autoClickCard); if (startBtnAutoClick != null) { @@ -228,7 +228,7 @@ public class PokemonGoGUI extends JFrame { )); logScrollPane.getViewport().setBackground(new Color(247, 247, 247)); - JButton clearLogButton = new JButton("🗑 Vyčistit log"); + JButton clearLogButton = new JButton("🗑 Clear log"); clearLogButton.setPreferredSize(new Dimension(140, 28)); styleButton(clearLogButton, ACCENT_BLUE, Color.WHITE, SMALL_FONT); clearLogButton.addActionListener(new ActionListener() { @@ -255,13 +255,13 @@ public class PokemonGoGUI extends JFrame { splitPane.setBorder(null); splitPane.setBackground(PANEL_BACKGROUND); - // Přidání do hlavního panelu + // Add to main panel mainPanel.add(headerPanel, BorderLayout.NORTH); mainPanel.add(splitPane, BorderLayout.CENTER); add(mainPanel); - // Klávesová zkratka: Ctrl+Alt+Q pro zastavení + // Keyboard shortcut: Ctrl+Alt+Q to stop KeyStroke hotkey = KeyStroke.getKeyStroke(KeyEvent.VK_Q, KeyEvent.CTRL_DOWN_MASK | KeyEvent.ALT_DOWN_MASK); getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(hotkey, "stopAutomationAction"); getRootPane().getActionMap().put("stopAutomationAction", new AbstractAction() { @@ -273,7 +273,7 @@ public class PokemonGoGUI extends JFrame { } }); - // Globální hotkey (funguje i když okno není fokusované) + // Global hotkey (works even when window is not focused) globalHotkey = new GlobalHotkey(new Runnable() { @Override public void run() { @@ -284,17 +284,17 @@ public class PokemonGoGUI extends JFrame { }); mainPanel.add(globalHotkey, BorderLayout.SOUTH); - // Přesměrování System.out a System.err do GUI + // Redirect System.out and System.err to 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+Q nebo klikněte ZASTAVIT.\n\n"); + logArea.append("=== Pokémon GO Automation ===\n\n"); + logArea.append("Select an automation and click START.\n"); + logArea.append("Make sure Pokémon GO is running.\n"); + logArea.append("To stop, press Ctrl+Alt+Q or click STOP.\n\n"); } /** - * Vytvoří kartu automatizace s nastavením + * Create automation card with settings */ private JPanel createAutomationCard(String title, String description, ActionListener startAction) { JPanel card = new JPanel(new BorderLayout(12, 12)); @@ -303,7 +303,7 @@ public class PokemonGoGUI extends JFrame { BorderFactory.createLineBorder(CARD_BORDER_COLOR, 1), BorderFactory.createEmptyBorder(8, 8, 8, 8) )); - card.setMaximumSize(new Dimension(CARD_MAX_WIDTH, 160)); + card.setMaximumSize(new Dimension(Integer.MAX_VALUE, 160)); card.setPreferredSize(new Dimension(CARD_MAX_WIDTH, 160)); card.setAlignmentX(Component.CENTER_ALIGNMENT); JPanel infoPanel = new JPanel(); @@ -330,9 +330,9 @@ public class PokemonGoGUI extends JFrame { centerPanel.setOpaque(true); if (title.contains("TRANSFER")) { - // Načíst hodnotu a zajistit, že je v platném rozsahu nebo v seznamu povolených hodnot + // Load value and ensure it is in valid range or in list of allowed values int savedCount = Integer.parseInt(settings.getProperty("transfer.count", "12")); - // Povolené hodnoty: 1, 3, 6, 12, 24, 36, 48, 60, 72, 84, 96 + // Allowed values: 1, 3, 6, 12, 24, 36, 48, 60, 72, 84, 96 int[] validCounts = {1, 3, 6, 12, 24, 36, 48, 60, 72, 84, 96}; boolean isValid = false; for (int count : validCounts) { @@ -342,10 +342,10 @@ public class PokemonGoGUI extends JFrame { } } if (!isValid) { - savedCount = 12; // Nastavit na výchozí, pokud není v seznamu povolených + savedCount = 12; // Set to default if not in allowed list } - // Vytvořit dropdown s hodnotami 1, 3, 6, 12, 24, 36, ..., 96 + // Create dropdown with values 1, 3, 6, 12, 24, 36, ..., 96 Integer[] counts = {1, 3, 6, 12, 24, 36, 48, 60, 72, 84, 96}; countComboBox = new JComboBox<>(counts); countComboBox.setSelectedItem(savedCount); @@ -360,9 +360,9 @@ public class PokemonGoGUI extends JFrame { card.putClientProperty("countComboBox", countComboBox); card.putClientProperty("delaySpinner", delaySpinner); - centerPanel.add(createFieldPanel("Počet:", countComboBox)); - centerPanel.add(createFieldPanel("Čekání (s):", delaySpinner)); - } else if (title.contains("AUTOKLIK")) { + centerPanel.add(createFieldPanel("Count:", countComboBox)); + centerPanel.add(createFieldPanel("Delay (s):", delaySpinner)); + } else if (title.contains("AUTOCLICK")) { JSpinner intervalSpinner = new JSpinner(new SpinnerNumberModel( Integer.parseInt(settings.getProperty("autoklik.interval", "100")), 10, 10000, 10 @@ -373,23 +373,23 @@ public class PokemonGoGUI extends JFrame { centerPanel.add(createFieldPanel("Interval (ms):", intervalSpinner)); } - // Pravý panel - START tlačítko (a u Autokliku i STOP v rámci tlačítka) + // Right panel - START button (and for Autoclick also STOP within the button) JPanel rightPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 6, 0)); rightPanel.setBackground(CARD_BACKGROUND); rightPanel.setBorder(BorderFactory.createEmptyBorder(4, 0, 0, 0)); - // Tlačítko START / VYPNOUT + // START / TURN OFF button JButton startBtn = new JButton("▶ START"); startBtn.setPreferredSize(new Dimension(100, 32)); styleButton(startBtn, PRIMARY_GREEN, Color.WHITE, SMALL_FONT); startBtn.addActionListener(startAction); - // Uložit tlačítko do card pro změnu barvy během běhu + // Save button to card for color change during run card.putClientProperty("startButton", startBtn); rightPanel.add(startBtn); - // Komponování karty: info nahoře, nastavení uprostřed, tlačítko dole + // Card composition: info on top, settings in middle, button at bottom card.add(infoPanel, BorderLayout.NORTH); card.add(centerPanel, BorderLayout.CENTER); card.add(rightPanel, BorderLayout.SOUTH); @@ -440,7 +440,7 @@ public class PokemonGoGUI extends JFrame { } /** - * Přesměruje System.out a System.err do log area + * Redirects System.out and System.err to log area */ private void redirectSystemStreams() { System.setOut(new java.io.PrintStream(System.out) { @@ -473,15 +473,15 @@ public class PokemonGoGUI extends JFrame { } /** - * Spustí Transfer automatizaci + * Start Transfer automation */ private void startTransferAutomation(JPanel transferCard) { if (isRunning) { - JOptionPane.showMessageDialog(this, "Automatizace již běží!", "Upozornění", JOptionPane.WARNING_MESSAGE); + JOptionPane.showMessageDialog(this, "Automation is already running!", "Warning", JOptionPane.WARNING_MESSAGE); return; } - // Získat počet pokémonů a čekání z GUI + // Get pokemon count and delay from GUI @SuppressWarnings("unchecked") JComboBox countComboBox = (JComboBox) transferCard.getClientProperty("countComboBox"); JSpinner delaySpinner = (JSpinner) transferCard.getClientProperty("delaySpinner"); @@ -490,11 +490,11 @@ public class PokemonGoGUI extends JFrame { int delaySeconds = (Integer) delaySpinner.getValue(); stopButton.setEnabled(true); - statusLabel.setText("Transfer automatizace běží..."); + statusLabel.setText("Transfer automation running..."); statusLabel.setForeground(new Color(255, 152, 0)); isRunning = true; - // Změnit barvu START tlačítka na červenou + // Change START button color to red JButton startBtn = (JButton) transferCard.getClientProperty("startButton"); if (startBtn != null) { startBtn.setEnabled(false); @@ -502,8 +502,8 @@ public class PokemonGoGUI extends JFrame { } 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("STARTING TRANSFER AUTOMATION\n"); + logArea.append("Pokémon count: " + pokemonCount + ", Delay: " + delaySeconds + "s\n"); logArea.append("========================================\n\n"); shouldStop = false; @@ -514,19 +514,19 @@ public class PokemonGoGUI extends JFrame { automation = new PokemonGoAutomation(); automation.resetTransferredCount(); - // Spustit vlákno pro aktualizaci statusu + // Start thread for status update 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 + Thread.sleep(500); // Update every 500ms final int transferred = automation.getTransferredCount(); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { if (isRunning) { - statusLabel.setText("Transfer běží... Transferováno: " + transferred + "/" + pokemonCount); + statusLabel.setText("Transfer running... Transferred: " + transferred + "/" + pokemonCount); } } }); @@ -548,9 +548,9 @@ public class PokemonGoGUI extends JFrame { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { - statusLabel.setText("Automatizace dokončena! Celkem transferováno: " + totalTransferredCount); + statusLabel.setText("Automation complete! Total transferred: " + totalTransferredCount); statusLabel.setForeground(new Color(76, 175, 80)); - logArea.append("\n✅ Transfer automatizace úspěšně dokončena! Transferováno: " + automation.getTransferredCount() + " pokémonů\n"); + logArea.append("\n✅ Transfer automation completed successfully! Transferred: " + automation.getTransferredCount() + "pokemon\n"); } }); } @@ -560,21 +560,21 @@ public class PokemonGoGUI extends JFrame { public void run() { statusLabel.setText("Chyba!"); statusLabel.setForeground(new Color(244, 67, 54)); - logArea.append("\n❌ Chyba: " + e.getMessage() + "\n"); + logArea.append("\n❌ Error: " + e.getMessage() + "\n"); e.printStackTrace(); } }); } finally { - // Čistit prostředky po automatizaci + // Clean up resources after automation try { if (automation != null) { automation.cleanup(); } - // Také vyčistit WindowFinder resources + // Also clean up WindowFinder resources WindowFinder.cleanup(); System.gc(); } catch (Exception cleanupEx) { - System.err.println("Chyba při čištění: " + cleanupEx.getMessage()); + System.err.println("Error during cleanup: " + cleanupEx.getMessage()); } SwingUtilities.invokeLater(new Runnable() { @@ -583,7 +583,7 @@ public class PokemonGoGUI extends JFrame { isRunning = false; stopButton.setEnabled(false); - // Vrátit barvu START tlačítka na zelenou + // Restore START button color to green JButton btn = (JButton) transferCard.getClientProperty("startButton"); if (btn != null) { btn.setEnabled(true); @@ -599,7 +599,7 @@ public class PokemonGoGUI extends JFrame { } /** - * Spustí autoklik + * Start autoclick */ private void startAutoClick(JPanel autoClickCard) { if (autoClickRunning) { @@ -608,36 +608,36 @@ public class PokemonGoGUI extends JFrame { } if (isRunning) { - JOptionPane.showMessageDialog(this, "Jiná automatizace již běží!", "Upozornění", JOptionPane.WARNING_MESSAGE); + JOptionPane.showMessageDialog(this, "Another automation is already running!", "Warning", JOptionPane.WARNING_MESSAGE); return; } - // Načtení nastavení + // Load settings JSpinner intervalSpinner = (JSpinner) autoClickCard.getClientProperty("intervalSpinner"); int interval = (Integer) intervalSpinner.getValue(); - // Uložení nastavení + // Save settings settings.setProperty("autoklik.interval", String.valueOf(interval)); saveSettings(); stopButton.setEnabled(true); - statusLabel.setText("Autokliker aktivní (Šipka dolů)..."); + statusLabel.setText("Autoclicker active (Down arrow)..."); statusLabel.setForeground(new Color(255, 152, 0)); isRunning = true; autoClickRunning = true; shouldStop = false; - // Změnit tlačítko na VYPNOUT + // Change button to TURN OFF JButton startBtn = (JButton) autoClickCard.getClientProperty("startButton"); if (startBtn != null) { - startBtn.setText("⏹ VYPNOUT"); + startBtn.setText("⏹ TURN OFF"); styleButton(startBtn, PRIMARY_RED, Color.WHITE, SMALL_FONT); } logArea.append("\n========================================\n"); - logArea.append("AUTOKLIKER AKTIVNÍ\n"); + logArea.append("AUTOCCLICKER ACTIVE\n"); logArea.append("Interval: " + interval + "ms\n"); - logArea.append("Ovládání: Stiskněte ŠIPKU NAHORU nebo DOLŮ pro zapnutí/vypnutí\n"); + logArea.append("Control: Press UP or DOWN ARROW to toggle\n"); logArea.append("========================================\n\n"); automationThread = new Thread(new Runnable() { @@ -652,44 +652,44 @@ public class PokemonGoGUI extends JFrame { long lastToggleTime = 0; while (autoClickRunning && !shouldStop) { - // Kontrola obou šipek + // Check both arrows boolean isKeyPressed = globalHotkey.isKeyPressed(KeyEvent.VK_DOWN) || globalHotkey.isKeyPressed(KeyEvent.VK_UP); long currentTime = System.currentTimeMillis(); - // Detekce stisku (náběžná hrana) pro přepnutí stavu + // Detect press (rising edge) to toggle state if (isKeyPressed && !wasKeyPressed && (currentTime - lastToggleTime > 200)) { isClickingActive = !isClickingActive; lastToggleTime = currentTime; final boolean active = isClickingActive; SwingUtilities.invokeLater(() -> { - logArea.append(active ? "▶ Klikání AKTIVOVÁNO šipkou\n" : "⏸ Klikání POZASTAVENO šipkou\n"); - statusLabel.setText(active ? "Autokliker: KLIKÁM..." : "Autokliker: POZASTAVENO"); + logArea.append(active ? "▶ Clicking ACTIVATED by arrow\n" : "⏸ Clicking PAUSED by arrow\n"); + statusLabel.setText(active ? "Autoclicker: CLICKING..." : "Autoclicker: PAUSED"); }); if (isClickingActive) { - lastClickTime = 0; // Spustit klikání hned + lastClickTime = 0; // Start clicking immediately } } wasKeyPressed = isKeyPressed; if (isClickingActive) { if (currentTime - lastClickTime >= interval) { - // Klik na aktuální pozici + // Click at current position robot.mousePress(java.awt.event.InputEvent.BUTTON1_DOWN_MASK); robot.mouseRelease(java.awt.event.InputEvent.BUTTON1_DOWN_MASK); clicksDone++; if (clicksDone % 20 == 0) { final int count = clicksDone; - SwingUtilities.invokeLater(() -> logArea.append(" Kliknutí: " + count + "\n")); + SwingUtilities.invokeLater(() -> logArea.append(" Clicks: " + count + "\n")); } lastClickTime = currentTime; } } - // Rychlá smyčka pro detekci kláves (10ms) + // Fast loop for key detection (10ms) Thread.sleep(10); } @@ -697,9 +697,9 @@ public class PokemonGoGUI extends JFrame { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { - statusLabel.setText("Autokliker zastaven."); + statusLabel.setText("Autoclicker stopped."); statusLabel.setForeground(new Color(76, 175, 80)); - logArea.append("\n✅ Autokliker byl vypnut.\n"); + logArea.append("\n✅ Autoclicker was turned off.\n"); } }); } @@ -710,9 +710,9 @@ public class PokemonGoGUI extends JFrame { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { - statusLabel.setText("Chyba autoklikeru!"); + statusLabel.setText("Autoclicker error!"); statusLabel.setForeground(new Color(244, 67, 54)); - logArea.append("\n❌ Chyba: " + e.getMessage() + "\n"); + logArea.append("\n❌ Error: " + e.getMessage() + "\n"); } }); } @@ -724,7 +724,7 @@ public class PokemonGoGUI extends JFrame { autoClickRunning = false; stopButton.setEnabled(false); - // Vrátit tlačítko na START + // Restore button to START JButton btn = (JButton) autoClickCard.getClientProperty("startButton"); if (btn != null) { btn.setText("▶ START"); @@ -740,7 +740,7 @@ public class PokemonGoGUI extends JFrame { } /** - * Zastaví automatizaci + * Stop automation */ private void stopAutomation() { if (!isRunning && !autoClickRunning) { @@ -757,7 +757,7 @@ public class PokemonGoGUI extends JFrame { if (automationThread != null && automationThread.isAlive()) { automationThread.interrupt(); - // Čekej max 2 sekundy na ukončení + // Wait max 2 seconds for shutdown try { automationThread.join(2000); } catch (InterruptedException e) { @@ -769,15 +769,15 @@ public class PokemonGoGUI extends JFrame { @Override public void run() { stopButton.setEnabled(false); - logArea.append("\n⚠️ Automatizace byla přerušena uživatelem\n"); - statusLabel.setText("Přerušeno"); + logArea.append("\n⚠️ Automation was interrupted by user\n"); + statusLabel.setText("Interrupted"); statusLabel.setForeground(new Color(244, 67, 54)); } }); } /** - * Načte uložená nastavení ze souboru + * Load saved settings from file */ private void loadSettings() { settings = new Properties(); @@ -787,11 +787,11 @@ public class PokemonGoGUI extends JFrame { 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()); + System.err.println("Error loading settings: " + e.getMessage()); } } - // Výchozí hodnoty, pokud nastavení neexistují + // Default values if settings do not exist if (!settings.containsKey("transfer.count")) { settings.setProperty("transfer.count", "12"); } @@ -813,10 +813,10 @@ public class PokemonGoGUI extends JFrame { } /** - * Uloží aktuální nastavení do souboru + * Save current settings to file */ private void saveSettings() { - // Uložení hodnot z combo boxu a spinneru + // Save values from combo box and spinner if (countComboBox != null) { settings.setProperty("transfer.count", countComboBox.getSelectedItem().toString()); } @@ -824,29 +824,29 @@ public class PokemonGoGUI extends JFrame { settings.setProperty("transfer.delay", delaySpinner.getValue().toString()); } - // Uložení velikosti a pozice okna + // Save window size and position 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í"); + settings.store(fos, "Pokémon GO Automation - Settings"); } catch (IOException e) { - System.err.println("Chyba při ukládání nastavení: " + e.getMessage()); + System.err.println("Error saving settings: " + e.getMessage()); } } public static void main(String[] args) { - // Nastavit shutdown hook pro bezpečné ukončení + // Set shutdown hook for safe shutdown Runtime.getRuntime().addShutdownHook(new Thread(() -> { - System.out.println("Aplikace se vypíná..."); + System.out.println("Application is shutting down..."); // Vyčistit X11 resources try { WindowFinder.cleanup(); } catch (Exception e) { - System.err.println("Chyba při čištění WindowFinder: " + e.getMessage()); + System.err.println("Error cleaning up WindowFinder: " + e.getMessage()); } })); @@ -856,11 +856,11 @@ public class PokemonGoGUI extends JFrame { PokemonGoGUI frame = new PokemonGoGUI(); frame.setVisible(true); - // Nastavit window listener pro čisté ukončení + // Set window listener for clean shutdown frame.addWindowListener(new java.awt.event.WindowAdapter() { @Override public void windowClosing(WindowEvent e) { - System.out.println("Zavírám okno..."); + System.out.println("Closing window..."); if (frame.globalHotkey != null) { frame.globalHotkey.cleanup(); } diff --git a/src/main/java/com/pokemongo/PositionPicker.java b/src/main/java/com/pokemongo/PositionPicker.java deleted file mode 100644 index 605efa4..0000000 --- a/src/main/java/com/pokemongo/PositionPicker.java +++ /dev/null @@ -1,102 +0,0 @@ -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 screenBounds = gd.getDefaultConfiguration().getBounds(); - - // Pokrýt celou obrazovku bez omezení insets - // (protože vrátíme absolutní globální souřadnice, ne relativní) - setBounds(screenBounds); - - System.out.println("PositionPicker vytvořen: " + screenBounds); - - 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) { - // Vrátit absolutní globální souřadnice na obrazovce - selectedPosition = new Point( - screenBounds.x + e.getX(), - screenBounds.y + 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; - } -} diff --git a/src/main/java/com/pokemongo/WindowFinder.java b/src/main/java/com/pokemongo/WindowFinder.java index 64067fb..7f0b489 100644 --- a/src/main/java/com/pokemongo/WindowFinder.java +++ b/src/main/java/com/pokemongo/WindowFinder.java @@ -11,8 +11,8 @@ import java.util.Arrays; import java.util.List; /** - * Pomocná třída pro hledání oken v Linux/X11 prostředí. - * Používá X11 API přes JNA bindings. + * Helper class for finding windows in Linux/X11 environment. + * Uses X11 API via JNA bindings. */ public class WindowFinder { @@ -25,7 +25,7 @@ public class WindowFinder { X11 INSTANCE = Native.load("X11", X11.class); /** - * X11 Window Attributes struktura - přesná kopie z X11/Xlib.h + * X11 Window Attributes structure - exact copy from X11/Xlib.h */ class XWindowAttributes extends Structure { public int x; @@ -79,13 +79,13 @@ public class WindowFinder { int XFetchName(Pointer display, long window, PointerByReference window_name_return); - // XTranslateCoordinates - převede souřadnice z jednoho okna do jiného (root) + // XTranslateCoordinates - converts coordinates from one window to another (root) boolean XTranslateCoordinates(Pointer display, long src_w, long dest_w, int src_x, int src_y, IntByReference dest_x_return, IntByReference dest_y_return, PointerByReference child_return); - // Globální klávesy + // Global keys int XQueryKeymap(Pointer display, byte[] keys_return); int XKeysymToKeycode(Pointer display, long keysym); @@ -93,9 +93,9 @@ public class WindowFinder { } /** - * Zjistí, zda je klávesa stisknuta globálně (i mimo fokus aplikace) - * @param keysym X11 Keysym (např. 0xFF54 pro Down Arrow) - * @return true pokud je klávesa držena + * Checks if a key is pressed globally (even outside application focus) + * @param keysym X11 Keysym (e.g. 0xFF54 for Down Arrow) + * @return true if key is held */ public static synchronized boolean isKeyPressedGlobally(long keysym) { Pointer display = null; @@ -128,51 +128,51 @@ public class WindowFinder { } /** - * Najde okno podle jeho názvu a vrátí jeho bounds - * @param searchPattern Pattern pro hledání (substring názvu okna) - * @return Rectangle s pozicí a velikostí okna, nebo null pokud nenalezeno + * Finds window by its name and returns its bounds + * @param searchPattern Pattern for searching (substring of window name) + * @return Rectangle with position and size of window, or null if not found */ public static synchronized Rectangle findWindowByName(String searchPattern) { Pointer display = null; try { - // Použít cachedDisplay pokud existuje, nebo otevřít nový + // Use cachedDisplay if it exists, or open new if (cachedDisplay != null) { display = cachedDisplay; - System.out.println("WindowFinder: Používám cachovaný X11 display"); + System.out.println("WindowFinder: Using cached X11 display"); } else { display = X11.INSTANCE.XOpenDisplay(null); if (display == null) { - System.out.println("WindowFinder: Nelze se připojit k X11 displei"); + System.out.println("WindowFinder: Cannot connect to X11 display"); return null; } cachedDisplay = display; - System.out.println("WindowFinder: Připojen k X11 displayu a uložen v cache"); + System.out.println("WindowFinder: Connected to X11 display and cached"); } long rootWindow = X11.INSTANCE.XDefaultRootWindow(display); - // Hledat okno a vrátit bounds + // Search for window and return bounds Rectangle bounds = searchWindowRecursiveWithBounds(display, rootWindow, searchPattern); if (bounds != null) { - System.out.println("WindowFinder: Okno nalezeno: " + bounds); + System.out.println("WindowFinder: Window found: " + bounds); return bounds; } - System.out.println("WindowFinder: Okno s názvem '" + searchPattern + "' nenalezeno"); + System.out.println("WindowFinder: Window with name '" + searchPattern + "' not found"); return null; } catch (Exception e) { - System.err.println("WindowFinder - Chyba: " + e.getMessage()); + System.err.println("WindowFinder - Error: " + e.getMessage()); e.printStackTrace(); - // Pokud dojde k chybě, vynulovat cache a zavřít display + // If error occurs, clear cache and close display if (display != null && display == cachedDisplay) { try { X11.INSTANCE.XCloseDisplay(display); cachedDisplay = null; } catch (Exception ex) { - System.err.println("WindowFinder - Chyba při zavírání displeje: " + ex.getMessage()); + System.err.println("WindowFinder - Error closing display: " + ex.getMessage()); } } return null; @@ -180,21 +180,21 @@ public class WindowFinder { } /** - * Rekurzivně hledá okno v stromě oken a vrátí jeho bounds při nalezení + * Recursively searches for window in window tree and returns its bounds when found */ private static Rectangle searchWindowRecursiveWithBounds(Pointer display, long window, String searchPattern) { try { String windowName = getWindowNameString(display, window); if (windowName != null && windowName.contains(searchPattern)) { - System.out.println("WindowFinder: Nalezeno okno: '" + windowName + "' (XID: " + window + ")"); + System.out.println("WindowFinder: Window found: '" + windowName + "' (XID: " + window + ")"); return getWindowBounds(display, window); } } catch (Exception e) { - // Ignorovat chyby při čtení jména okna + // Ignore errors when reading window name } - // Hledat v potomcích + // Search in children PointerByReference children_return = new PointerByReference(); IntByReference nchildren_return = new IntByReference(); @@ -210,7 +210,7 @@ public class WindowFinder { int numChildren = nchildren_return.getValue(); if (childrenPtr != null) { - // Čtení window IDs z pole + // Reading window IDs from array for (int i = 0; i < numChildren; i++) { long childWindow = childrenPtr.getLong((long) i * 8); // 64-bit window IDs @@ -224,14 +224,14 @@ public class WindowFinder { } } } catch (Exception e) { - // Ignorovat chyby při hledání v potomcích + // Ignore errors when searching in children } return null; } /** - * Získá jméno okna jako String + * Gets window name as String */ private static String getWindowNameString(Pointer display, long window) { PointerByReference namePtr = new PointerByReference(); @@ -258,8 +258,8 @@ public class WindowFinder { } /** - * Získá bounds okna (pozici a velikost) - ABSOLUTNÍ pozici na obrazovce - * Používá XTranslateCoordinates na správný převod souřadnic z okna do root + * Gets window bounds (position and size) - ABSOLUTE position on screen + * Uses XTranslateCoordinates for correct conversion of coordinates from window to root */ private static Rectangle getWindowBounds(Pointer display, Long window) { try { @@ -267,11 +267,11 @@ public class WindowFinder { int status = X11.INSTANCE.XGetWindowAttributes(display, window, attrs); if (status == 0) { - System.err.println("WindowFinder - Chyba při získávání window attributes"); + System.err.println("WindowFinder - Error getting window attributes"); return null; } - // Použít XTranslateCoordinates na převod souřadnic z okna do root + // Use XTranslateCoordinates to convert coordinates from window to root long rootWindow = X11.INSTANCE.XDefaultRootWindow(display); IntByReference absX = new IntByReference(); IntByReference absY = new IntByReference(); @@ -281,21 +281,21 @@ public class WindowFinder { 0, 0, absX, absY, child); if (!translated) { - System.err.println("WindowFinder - Chyba při XTranslateCoordinates"); - // Fallback - vrátit alespoň relativní pozici + System.err.println("WindowFinder - Error in XTranslateCoordinates"); + // Fallback - return at least relative position return new Rectangle(attrs.x, attrs.y, attrs.width, attrs.height); } int absoluteX = absX.getValue(); int absoluteY = absY.getValue(); - System.out.println("WindowFinder: Window bounds - ABSOLUTNÍ: x:" + absoluteX + " y:" + absoluteY + + System.out.println("WindowFinder: Window bounds - ABSOLUTE: x:" + absoluteX + " y:" + absoluteY + " w:" + attrs.width + " h:" + attrs.height); return new Rectangle(absoluteX, absoluteY, attrs.width, attrs.height); } catch (Exception e) { - System.err.println("WindowFinder - Chyba při získávání bounds: " + e.getMessage()); + System.err.println("WindowFinder - Error getting bounds: " + e.getMessage()); e.printStackTrace(); } @@ -303,16 +303,16 @@ public class WindowFinder { } /** - * Ukončí X11 display connection a vyčistí cache - * Volat při shutdown aplikace + * Closes X11 display connection and clears cache + * Call on application shutdown */ public static synchronized void cleanup() { if (cachedDisplay != null) { try { X11.INSTANCE.XCloseDisplay(cachedDisplay); - System.out.println("WindowFinder: X11 display uzavřen a cache vyčištěn"); + System.out.println("WindowFinder: X11 display closed and cache cleared"); } catch (Exception e) { - System.err.println("WindowFinder - Chyba při zavírání displeje: " + e.getMessage()); + System.err.println("WindowFinder - Error closing display: " + e.getMessage()); } finally { cachedDisplay = null; }