pgo-automation/src/main/java/com/pokemongo/PokemonGoGUI.java
2026-01-23 16:04:46 +01:00

863 lines
36 KiB
Java
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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