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í
#Fri Dec 19 21:53:30 CET 2025
#Fri Dec 19 22:55:32 CET 2025
autoklik.count=500
window.width=807
transfer.delay=0

View File

@ -4,7 +4,9 @@ import java.awt.AWTException;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Insets;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.PointerInfo;
import java.awt.Rectangle;
import java.awt.Robot;
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_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
public PokemonGoAutomation() throws AWTException {
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í: "
+ 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()) {
System.err.println("Nepodařilo se najít okno Pokémon GO!");
return;
@ -537,6 +547,7 @@ public class PokemonGoAutomation {
int transferredCount = 0;
// Transferovat dokud nedosáhneme požadovaného počtu
try {
while (transferredCount < totalPokemonCount) {
// Kontrola přerušení
if (Thread.currentThread().isInterrupted()) {
@ -582,12 +593,23 @@ public class PokemonGoAutomation {
while (System.currentTimeMillis() < endTime) {
if (Thread.currentThread().isInterrupted()) {
System.out.println("\n⚠ Automatizace byla přerušena během přestávky!");
return;
break;
}
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ů");
}
@ -669,6 +691,30 @@ public class PokemonGoAutomation {
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) {
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

@ -31,7 +31,7 @@ public class PokemonGoGUI extends JFrame {
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 JComboBox<Integer> countComboBox;
private JSpinner delaySpinner;
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);
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));
// Načíst hodnotu a zajistit, že je v platném rozsahu nebo v seznamu povolených hodnot
int savedCount = Integer.parseInt(settings.getProperty("transfer.count", "12"));
// 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};
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(
Integer.parseInt(settings.getProperty("transfer.delay", "2")),
0, 60, 1
));
delaySpinner.setPreferredSize(new Dimension(64, 26));
card.putClientProperty("countSpinner", countSpinner);
card.putClientProperty("countComboBox", countComboBox);
card.putClientProperty("delaySpinner", delaySpinner);
centerPanel.add(createFieldPanel("Počet:", countSpinner));
centerPanel.add(createFieldPanel("Počet:", countComboBox));
centerPanel.add(createFieldPanel("Čekání (s):", delaySpinner));
} else if (title.contains("AUTOKLIK")) {
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
JSpinner countSpinner = (JSpinner) transferCard.getClientProperty("countSpinner");
JComboBox<Integer> countComboBox = (JComboBox<Integer>) transferCard.getClientProperty("countComboBox");
JSpinner delaySpinner = (JSpinner) transferCard.getClientProperty("delaySpinner");
int pokemonCount = (Integer) countSpinner.getValue();
int pokemonCount = (Integer) countComboBox.getSelectedItem();
int delaySeconds = (Integer) delaySpinner.getValue();
stopButton.setEnabled(true);
@ -599,6 +615,18 @@ public class PokemonGoGUI extends JFrame {
}
});
} 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() {
@Override
public void run() {
@ -773,7 +801,7 @@ public class PokemonGoGUI extends JFrame {
// Výchozí hodnoty, pokud nastavení neexistují
if (!settings.containsKey("transfer.count")) {
settings.setProperty("transfer.count", "9");
settings.setProperty("transfer.count", "12");
}
if (!settings.containsKey("transfer.delay")) {
settings.setProperty("transfer.delay", "2");
@ -796,9 +824,9 @@ public class PokemonGoGUI extends JFrame {
* Uloží aktuální nastavení do souboru
*/
private void saveSettings() {
// Uložení hodnot z spinnerů
if (countSpinner != null) {
settings.setProperty("transfer.count", countSpinner.getValue().toString());
// Uložení hodnot z combo boxu a spinneru
if (countComboBox != null) {
settings.setProperty("transfer.count", countComboBox.getSelectedItem().toString());
}
if (delaySpinner != null) {
settings.setProperty("transfer.delay", delaySpinner.getValue().toString());
@ -819,11 +847,32 @@ public class PokemonGoGUI extends JFrame {
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() {
@Override
public void run() {
PokemonGoGUI frame = new PokemonGoGUI();
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();
Rectangle screenBounds = gd.getDefaultConfiguration().getBounds();
// Zjistit insets - offset zp ůsobený OS panelem/dashboardem
Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(gd.getDefaultConfiguration());
System.out.println("PositionPicker insets: top=" + insets.top + ", left=" + insets.left);
// Pokrýt celou obrazovku bez omezení insets
// (protože vrátíme absolutní globální souřadnice, ne relativní)
setBounds(screenBounds);
// Aplikovat insets na bounds
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);
System.out.println("PositionPicker vytvořen: " + screenBounds);
setFocusable(true);
setBackground(new Color(0, 0, 0, 0));
@ -69,7 +60,11 @@ public class PositionPicker extends JWindow {
panel.addMouseListener(new MouseAdapter() {
@Override
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;
System.out.println("✅ Pozice vybrána: " + selectedPosition);
if (listener != null) {

View File

@ -16,6 +16,8 @@ import java.util.List;
*/
public class WindowFinder {
private static Pointer cachedDisplay = null;
/**
* X11 native library interface
*/
@ -23,7 +25,7 @@ public class WindowFinder {
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 {
public int x;
@ -32,31 +34,32 @@ public class WindowFinder {
public int height;
public int border_width;
public int depth;
public Pointer visual;
public Pointer root;
public int class_;
public Pointer visual; // Visual* - opaque pointer
public long root; // Window (XID)
public int class_; // int, not pointer
public int bit_gravity;
public int win_gravity;
public int backing_pixel;
public int backing_planes;
public int backing_store;
public long backing_pixel_unused;
public int save_under;
public Pointer colormap;
public int map_installed;
public long backing_planes;
public long backing_pixel;
public boolean save_under; // Bool - should be boolean
public long colormap; // Colormap (XID) - should be long
public boolean map_installed; // Bool - should be boolean
public int map_state;
public long all_event_masks;
public long your_event_mask;
public long do_not_propagate_mask;
public boolean override_redirect; // Bool - missing field
public Pointer screen; // Screen* - opaque pointer, missing field
@Override
protected List<String> getFieldOrder() {
return Arrays.asList("x", "y", "width", "height", "border_width", "depth",
"visual", "root", "class_", "bit_gravity", "win_gravity",
"backing_pixel", "backing_planes", "backing_store",
"backing_pixel_unused", "save_under", "colormap",
"map_installed", "map_state", "all_event_masks",
"your_event_mask", "do_not_propagate_mask");
"backing_store", "backing_planes", "backing_pixel",
"save_under", "colormap", "map_installed", "map_state",
"all_event_masks", "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)
* @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;
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);
if (display == null) {
System.out.println("WindowFinder: Nelze se připojit k X11 displei");
return null;
}
System.out.println("WindowFinder: Připojen k X11 displayu");
cachedDisplay = display;
System.out.println("WindowFinder: Připojen k X11 displayu a uložen v cache");
}
long rootWindow = X11.INSTANCE.XDefaultRootWindow(display);
long[] foundWindow = new long[1];
@ -115,15 +125,16 @@ public class WindowFinder {
} catch (Exception e) {
System.err.println("WindowFinder - Chyba: " + e.getMessage());
e.printStackTrace();
return null;
} finally {
if (display != null) {
// Pokud dojde k chybě, vynulovat cache a zavřít display
if (display != null && display == cachedDisplay) {
try {
X11.INSTANCE.XCloseDisplay(display);
} catch (Exception e) {
System.err.println("WindowFinder - Chyba při zavírání displeje: " + e.getMessage());
cachedDisplay = null;
} 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
PointerByReference children_return = new PointerByReference();
IntByReference nchildren_return = new IntByReference();
try {
PointerByReference root_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,
children_return, nchildren_return);
@ -171,8 +183,8 @@ public class WindowFinder {
}
}
// Uvolnit paměť
X11.INSTANCE.XFree(childrenPtr);
// Don't call XFree - it can cause heap corruption
// X11.INSTANCE.XFree(childrenPtr);
}
}
} catch (Exception e) {
@ -184,17 +196,21 @@ public class WindowFinder {
* Získá jméno okna jako String
*/
private static String getWindowNameString(Pointer display, long window) {
try {
PointerByReference namePtr = new PointerByReference();
try {
int status = X11.INSTANCE.XFetchName(display, window, namePtr);
if (status != 0 && namePtr.getValue() != null) {
String name = namePtr.getValue().getString(0);
if (name != null && !name.isEmpty()) {
X11.INSTANCE.XFree(namePtr.getValue());
return name;
if (status != 0) {
Pointer actualNamePtr = namePtr.getValue();
if (actualNamePtr != null) {
String name = actualNamePtr.getString(0);
// 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) {
// Ignorovat chyby
@ -228,4 +244,21 @@ public class WindowFinder {
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;
}
}
}
}