transfer fixes

This commit is contained in:
Radek Davidek 2025-12-19 22:58:50 +01:00
parent 162aa6d7ab
commit 444fd73bb2
5 changed files with 192 additions and 69 deletions

View File

@ -1,5 +1,5 @@
#Pokémon GO Automatizace - Nastavení #Pokémon GO Automatizace - Nastavení
#Fri Dec 19 21:53:30 CET 2025 #Fri Dec 19 22:55:32 CET 2025
autoklik.count=500 autoklik.count=500
window.width=807 window.width=807
transfer.delay=0 transfer.delay=0

View File

@ -4,7 +4,9 @@ import java.awt.AWTException;
import java.awt.GraphicsDevice; import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment; import java.awt.GraphicsEnvironment;
import java.awt.Insets; import java.awt.Insets;
import java.awt.MouseInfo;
import java.awt.Point; import java.awt.Point;
import java.awt.PointerInfo;
import java.awt.Rectangle; import java.awt.Rectangle;
import java.awt.Robot; import java.awt.Robot;
import java.awt.Toolkit; import java.awt.Toolkit;
@ -32,6 +34,7 @@ public class PokemonGoAutomation {
private static final int DELAY_BETWEEN_CLICKS = 100; // ms private static final int DELAY_BETWEEN_CLICKS = 100; // ms
private static final int DELAY_AFTER_ACTION = 100; // ms private static final int DELAY_AFTER_ACTION = 100; // ms
private int transferredPokemonCount = 0; // Počet transfernutých pokémonů private int transferredPokemonCount = 0; // Počet transfernutých pokémonů
private Point initialMousePosition = null; // Pozice kurzoru před začátkem automatizace
public PokemonGoAutomation() throws AWTException { public PokemonGoAutomation() throws AWTException {
this.robot = new Robot(); this.robot = new Robot();
@ -524,6 +527,13 @@ public class PokemonGoAutomation {
System.out.println("Spouštím Transfer automatizaci - Počet pokémonů: " + totalPokemonCount + ", Čekání: " System.out.println("Spouštím Transfer automatizaci - Počet pokémonů: " + totalPokemonCount + ", Čekání: "
+ delaySeconds + "s"); + delaySeconds + "s");
// Uložit aktuální pozici kurzoru
PointerInfo pointerInfo = MouseInfo.getPointerInfo();
initialMousePosition = pointerInfo != null ? pointerInfo.getLocation() : null;
if (initialMousePosition != null) {
System.out.println("Uložena počáteční pozice kurzoru: " + initialMousePosition);
}
if (!findPokemonGoWindow()) { if (!findPokemonGoWindow()) {
System.err.println("Nepodařilo se najít okno Pokémon GO!"); System.err.println("Nepodařilo se najít okno Pokémon GO!");
return; return;
@ -537,6 +547,7 @@ public class PokemonGoAutomation {
int transferredCount = 0; int transferredCount = 0;
// Transferovat dokud nedosáhneme požadovaného počtu // Transferovat dokud nedosáhneme požadovaného počtu
try {
while (transferredCount < totalPokemonCount) { while (transferredCount < totalPokemonCount) {
// Kontrola přerušení // Kontrola přerušení
if (Thread.currentThread().isInterrupted()) { if (Thread.currentThread().isInterrupted()) {
@ -582,12 +593,23 @@ public class PokemonGoAutomation {
while (System.currentTimeMillis() < endTime) { while (System.currentTimeMillis() < endTime) {
if (Thread.currentThread().isInterrupted()) { if (Thread.currentThread().isInterrupted()) {
System.out.println("\n⚠ Automatizace byla přerušena během přestávky!"); System.out.println("\n⚠ Automatizace byla přerušena během přestávky!");
return; break;
} }
robot.delay(100); robot.delay(100);
} }
} }
} }
} finally {
// Obnovit pozici kurzoru
if (initialMousePosition != null) {
try {
robot.mouseMove(initialMousePosition.x, initialMousePosition.y);
System.out.println("Kurzor vrácen na počáteční pozici: " + initialMousePosition);
} catch (Exception e) {
System.err.println("Chyba při obnovení pozice kurzoru: " + e.getMessage());
}
}
}
System.out.println("\n✅ Transfer automatizace dokončena! Transferováno: " + transferredCount + " pokémonů"); System.out.println("\n✅ Transfer automatizace dokončena! Transferováno: " + transferredCount + " pokémonů");
} }
@ -669,6 +691,30 @@ public class PokemonGoAutomation {
return new Point(absoluteX, absoluteY); return new Point(absoluteX, absoluteY);
} }
/**
* Vyčistí všechny prostředky používané automatizací
* Volat po skončení automatizace
*/
public void cleanup() {
try {
System.out.println("Čištění prostředků automatizace...");
// Uvolnit reference na obrázky
t1Template = null;
t2Template = null;
t3Template = null;
pok1Template = null;
includeTemplate = null;
windowBounds = null;
// Explicitně vyvolat garbage collector
System.gc();
System.out.println("Prostředky automatizace vyčištěny");
} catch (Exception e) {
System.err.println("Chyba při čištění prostředků: " + e.getMessage());
}
}
public static void main(String[] args) { public static void main(String[] args) {
System.out.println("=== Pokémon GO Automatizační Nástroj ==="); 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("Ujistěte se, že je aplikace Pokémon GO spuštěná...");

View File

@ -31,7 +31,7 @@ public class PokemonGoGUI extends JFrame {
private static final String CONFIG_FILE = "pgo-automat-settings.properties"; private static final String CONFIG_FILE = "pgo-automat-settings.properties";
private static final String VERSION = "1.0.2"; private static final String VERSION = "1.0.2";
private Properties settings; private Properties settings;
private JSpinner countSpinner; private JComboBox<Integer> countComboBox;
private JSpinner delaySpinner; private JSpinner delaySpinner;
private static final Font TITLE_FONT = new Font("Segoe UI", Font.BOLD, 18); private static final Font TITLE_FONT = new Font("Segoe UI", Font.BOLD, 18);
@ -330,21 +330,37 @@ public class PokemonGoGUI extends JFrame {
centerPanel.setOpaque(true); centerPanel.setOpaque(true);
if (title.contains("TRANSFER")) { if (title.contains("TRANSFER")) {
countSpinner = new JSpinner(new SpinnerNumberModel( // Načíst hodnotu a zajistit, že je v platném rozsahu nebo v seznamu povolených hodnot
Integer.parseInt(settings.getProperty("transfer.count", "9")), int savedCount = Integer.parseInt(settings.getProperty("transfer.count", "12"));
1, 999, 1 // Povolené hodnoty: 1, 3, 6, 12, 24, 36, 48, 60, 72, 84, 96
)); int[] validCounts = {1, 3, 6, 12, 24, 36, 48, 60, 72, 84, 96};
countSpinner.setPreferredSize(new Dimension(64, 26)); boolean isValid = false;
for (int count : validCounts) {
if (savedCount == count) {
isValid = true;
break;
}
}
if (!isValid) {
savedCount = 12; // Nastavit na výchozí, pokud není v seznamu povolených
}
// Vytvořit dropdown s hodnotami 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);
countComboBox.setPreferredSize(new Dimension(70, 26));
delaySpinner = new JSpinner(new SpinnerNumberModel( delaySpinner = new JSpinner(new SpinnerNumberModel(
Integer.parseInt(settings.getProperty("transfer.delay", "2")), Integer.parseInt(settings.getProperty("transfer.delay", "2")),
0, 60, 1 0, 60, 1
)); ));
delaySpinner.setPreferredSize(new Dimension(64, 26)); delaySpinner.setPreferredSize(new Dimension(64, 26));
card.putClientProperty("countSpinner", countSpinner); card.putClientProperty("countComboBox", countComboBox);
card.putClientProperty("delaySpinner", delaySpinner); card.putClientProperty("delaySpinner", delaySpinner);
centerPanel.add(createFieldPanel("Počet:", countSpinner)); centerPanel.add(createFieldPanel("Počet:", countComboBox));
centerPanel.add(createFieldPanel("Čekání (s):", delaySpinner)); centerPanel.add(createFieldPanel("Čekání (s):", delaySpinner));
} else if (title.contains("AUTOKLIK")) { } else if (title.contains("AUTOKLIK")) {
JSpinner xSpinner = new JSpinner(new SpinnerNumberModel( JSpinner xSpinner = new JSpinner(new SpinnerNumberModel(
@ -524,10 +540,10 @@ public class PokemonGoGUI extends JFrame {
} }
// Získat počet pokémonů a čekání z GUI // Získat počet pokémonů a čekání z GUI
JSpinner countSpinner = (JSpinner) transferCard.getClientProperty("countSpinner"); JComboBox<Integer> countComboBox = (JComboBox<Integer>) transferCard.getClientProperty("countComboBox");
JSpinner delaySpinner = (JSpinner) transferCard.getClientProperty("delaySpinner"); JSpinner delaySpinner = (JSpinner) transferCard.getClientProperty("delaySpinner");
int pokemonCount = (Integer) countSpinner.getValue(); int pokemonCount = (Integer) countComboBox.getSelectedItem();
int delaySeconds = (Integer) delaySpinner.getValue(); int delaySeconds = (Integer) delaySpinner.getValue();
stopButton.setEnabled(true); stopButton.setEnabled(true);
@ -599,6 +615,18 @@ public class PokemonGoGUI extends JFrame {
} }
}); });
} finally { } finally {
// Čistit prostředky po automatizaci
try {
if (automation != null) {
automation.cleanup();
}
// Také vyčistit WindowFinder resources
WindowFinder.cleanup();
System.gc();
} catch (Exception cleanupEx) {
System.err.println("Chyba při čištění: " + cleanupEx.getMessage());
}
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(new Runnable() {
@Override @Override
public void run() { public void run() {
@ -773,7 +801,7 @@ public class PokemonGoGUI extends JFrame {
// Výchozí hodnoty, pokud nastavení neexistují // Výchozí hodnoty, pokud nastavení neexistují
if (!settings.containsKey("transfer.count")) { if (!settings.containsKey("transfer.count")) {
settings.setProperty("transfer.count", "9"); settings.setProperty("transfer.count", "12");
} }
if (!settings.containsKey("transfer.delay")) { if (!settings.containsKey("transfer.delay")) {
settings.setProperty("transfer.delay", "2"); settings.setProperty("transfer.delay", "2");
@ -796,9 +824,9 @@ public class PokemonGoGUI extends JFrame {
* Uloží aktuální nastavení do souboru * Uloží aktuální nastavení do souboru
*/ */
private void saveSettings() { private void saveSettings() {
// Uložení hodnot z spinnerů // Uložení hodnot z combo boxu a spinneru
if (countSpinner != null) { if (countComboBox != null) {
settings.setProperty("transfer.count", countSpinner.getValue().toString()); settings.setProperty("transfer.count", countComboBox.getSelectedItem().toString());
} }
if (delaySpinner != null) { if (delaySpinner != null) {
settings.setProperty("transfer.delay", delaySpinner.getValue().toString()); settings.setProperty("transfer.delay", delaySpinner.getValue().toString());
@ -819,11 +847,32 @@ public class PokemonGoGUI extends JFrame {
public static void main(String[] args) { public static void main(String[] args) {
// Nastavit shutdown hook pro bezpečné ukončení
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
System.out.println("Aplikace se vypíná...");
// Vyčistit X11 resources
try {
WindowFinder.cleanup();
} catch (Exception e) {
System.err.println("Chyba při čištění WindowFinder: " + e.getMessage());
}
}));
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(new Runnable() {
@Override @Override
public void run() { public void run() {
PokemonGoGUI frame = new PokemonGoGUI(); PokemonGoGUI frame = new PokemonGoGUI();
frame.setVisible(true); frame.setVisible(true);
// Nastavit window listener pro čisté ukončení
frame.addWindowListener(new java.awt.event.WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.out.println("Zavírám okno...");
frame.saveSettings();
System.exit(0);
}
});
} }
}); });
} }

View File

@ -22,20 +22,11 @@ public class PositionPicker extends JWindow {
GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice(); GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
Rectangle screenBounds = gd.getDefaultConfiguration().getBounds(); Rectangle screenBounds = gd.getDefaultConfiguration().getBounds();
// Zjistit insets - offset zp ůsobený OS panelem/dashboardem // Pokrýt celou obrazovku bez omezení insets
Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(gd.getDefaultConfiguration()); // (protože vrátíme absolutní globální souřadnice, ne relativní)
System.out.println("PositionPicker insets: top=" + insets.top + ", left=" + insets.left); setBounds(screenBounds);
// Aplikovat insets na bounds System.out.println("PositionPicker vytvořen: " + screenBounds);
Rectangle bounds = new Rectangle(
screenBounds.x + insets.left,
screenBounds.y + insets.top,
screenBounds.width - insets.left - insets.right,
screenBounds.height - insets.top - insets.bottom
);
setBounds(bounds);
System.out.println("PositionPicker vytvořen: " + bounds);
setFocusable(true); setFocusable(true);
setBackground(new Color(0, 0, 0, 0)); setBackground(new Color(0, 0, 0, 0));
@ -69,7 +60,11 @@ public class PositionPicker extends JWindow {
panel.addMouseListener(new MouseAdapter() { panel.addMouseListener(new MouseAdapter() {
@Override @Override
public void mouseClicked(MouseEvent e) { public void mouseClicked(MouseEvent e) {
selectedPosition = new Point(e.getX(), e.getY()); // Vrátit absolutní globální souřadnice na obrazovce
selectedPosition = new Point(
screenBounds.x + e.getX(),
screenBounds.y + e.getY()
);
positionSelected = true; positionSelected = true;
System.out.println("✅ Pozice vybrána: " + selectedPosition); System.out.println("✅ Pozice vybrána: " + selectedPosition);
if (listener != null) { if (listener != null) {

View File

@ -16,6 +16,8 @@ import java.util.List;
*/ */
public class WindowFinder { public class WindowFinder {
private static Pointer cachedDisplay = null;
/** /**
* X11 native library interface * X11 native library interface
*/ */
@ -23,7 +25,7 @@ public class WindowFinder {
X11 INSTANCE = Native.load("X11", X11.class); X11 INSTANCE = Native.load("X11", X11.class);
/** /**
* X11 Window Attributes struktura * X11 Window Attributes struktura - přesná kopie z X11/Xlib.h
*/ */
class XWindowAttributes extends Structure { class XWindowAttributes extends Structure {
public int x; public int x;
@ -32,31 +34,32 @@ public class WindowFinder {
public int height; public int height;
public int border_width; public int border_width;
public int depth; public int depth;
public Pointer visual; public Pointer visual; // Visual* - opaque pointer
public Pointer root; public long root; // Window (XID)
public int class_; public int class_; // int, not pointer
public int bit_gravity; public int bit_gravity;
public int win_gravity; public int win_gravity;
public int backing_pixel;
public int backing_planes;
public int backing_store; public int backing_store;
public long backing_pixel_unused; public long backing_planes;
public int save_under; public long backing_pixel;
public Pointer colormap; public boolean save_under; // Bool - should be boolean
public int map_installed; public long colormap; // Colormap (XID) - should be long
public boolean map_installed; // Bool - should be boolean
public int map_state; public int map_state;
public long all_event_masks; public long all_event_masks;
public long your_event_mask; public long your_event_mask;
public long do_not_propagate_mask; public long do_not_propagate_mask;
public boolean override_redirect; // Bool - missing field
public Pointer screen; // Screen* - opaque pointer, missing field
@Override @Override
protected List<String> getFieldOrder() { protected List<String> getFieldOrder() {
return Arrays.asList("x", "y", "width", "height", "border_width", "depth", return Arrays.asList("x", "y", "width", "height", "border_width", "depth",
"visual", "root", "class_", "bit_gravity", "win_gravity", "visual", "root", "class_", "bit_gravity", "win_gravity",
"backing_pixel", "backing_planes", "backing_store", "backing_store", "backing_planes", "backing_pixel",
"backing_pixel_unused", "save_under", "colormap", "save_under", "colormap", "map_installed", "map_state",
"map_installed", "map_state", "all_event_masks", "all_event_masks", "your_event_mask", "do_not_propagate_mask",
"your_event_mask", "do_not_propagate_mask"); "override_redirect", "screen");
} }
} }
@ -84,16 +87,23 @@ public class WindowFinder {
* @param searchPattern Pattern pro hledání (substring názvu okna) * @param searchPattern Pattern pro hledání (substring názvu okna)
* @return Rectangle s pozicí a velikostí okna, nebo null pokud nenalezeno * @return Rectangle s pozicí a velikostí okna, nebo null pokud nenalezeno
*/ */
public static Rectangle findWindowByName(String searchPattern) { public static synchronized Rectangle findWindowByName(String searchPattern) {
Pointer display = null; Pointer display = null;
try { try {
// Použít cachedDisplay pokud existuje, nebo otevřít nový
if (cachedDisplay != null) {
display = cachedDisplay;
System.out.println("WindowFinder: Používám cachovaný X11 display");
} else {
display = X11.INSTANCE.XOpenDisplay(null); display = X11.INSTANCE.XOpenDisplay(null);
if (display == null) { if (display == null) {
System.out.println("WindowFinder: Nelze se připojit k X11 displei"); System.out.println("WindowFinder: Nelze se připojit k X11 displei");
return null; return null;
} }
cachedDisplay = display;
System.out.println("WindowFinder: Připojen k X11 displayu"); System.out.println("WindowFinder: Připojen k X11 displayu a uložen v cache");
}
long rootWindow = X11.INSTANCE.XDefaultRootWindow(display); long rootWindow = X11.INSTANCE.XDefaultRootWindow(display);
long[] foundWindow = new long[1]; long[] foundWindow = new long[1];
@ -115,15 +125,16 @@ public class WindowFinder {
} catch (Exception e) { } catch (Exception e) {
System.err.println("WindowFinder - Chyba: " + e.getMessage()); System.err.println("WindowFinder - Chyba: " + e.getMessage());
e.printStackTrace(); e.printStackTrace();
return null; // Pokud dojde k chybě, vynulovat cache a zavřít display
} finally { if (display != null && display == cachedDisplay) {
if (display != null) {
try { try {
X11.INSTANCE.XCloseDisplay(display); X11.INSTANCE.XCloseDisplay(display);
} catch (Exception e) { cachedDisplay = null;
System.err.println("WindowFinder - Chyba při zavírání displeje: " + e.getMessage()); } catch (Exception ex) {
System.err.println("WindowFinder - Chyba při zavírání displeje: " + ex.getMessage());
} }
} }
return null;
} }
} }
@ -148,11 +159,12 @@ public class WindowFinder {
} }
// Hledat v potomcích // Hledat v potomcích
PointerByReference children_return = new PointerByReference();
IntByReference nchildren_return = new IntByReference();
try { try {
PointerByReference root_return = new PointerByReference(); PointerByReference root_return = new PointerByReference();
PointerByReference parent_return = new PointerByReference(); PointerByReference parent_return = new PointerByReference();
PointerByReference children_return = new PointerByReference();
IntByReference nchildren_return = new IntByReference();
int status = X11.INSTANCE.XQueryTree(display, window, root_return, parent_return, int status = X11.INSTANCE.XQueryTree(display, window, root_return, parent_return,
children_return, nchildren_return); children_return, nchildren_return);
@ -171,8 +183,8 @@ public class WindowFinder {
} }
} }
// Uvolnit paměť // Don't call XFree - it can cause heap corruption
X11.INSTANCE.XFree(childrenPtr); // X11.INSTANCE.XFree(childrenPtr);
} }
} }
} catch (Exception e) { } catch (Exception e) {
@ -184,17 +196,21 @@ public class WindowFinder {
* Získá jméno okna jako String * Získá jméno okna jako String
*/ */
private static String getWindowNameString(Pointer display, long window) { private static String getWindowNameString(Pointer display, long window) {
try {
PointerByReference namePtr = new PointerByReference(); PointerByReference namePtr = new PointerByReference();
try {
int status = X11.INSTANCE.XFetchName(display, window, namePtr); int status = X11.INSTANCE.XFetchName(display, window, namePtr);
if (status != 0 && namePtr.getValue() != null) { if (status != 0) {
String name = namePtr.getValue().getString(0); Pointer actualNamePtr = namePtr.getValue();
if (name != null && !name.isEmpty()) { if (actualNamePtr != null) {
X11.INSTANCE.XFree(namePtr.getValue()); String name = actualNamePtr.getString(0);
return name;
// Don't call XFree - it can cause heap corruption
// X11.INSTANCE.XFree(actualNamePtr);
return (name != null && !name.isEmpty()) ? name : null;
} }
X11.INSTANCE.XFree(namePtr.getValue());
} }
} catch (Exception e) { } catch (Exception e) {
// Ignorovat chyby // Ignorovat chyby
@ -228,4 +244,21 @@ public class WindowFinder {
return null; return null;
} }
/**
* Ukončí X11 display connection a vyčistí cache
* Volat při shutdown aplikace
*/
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");
} catch (Exception e) {
System.err.println("WindowFinder - Chyba při zavírání displeje: " + e.getMessage());
} finally {
cachedDisplay = null;
}
}
}
} }