863 lines
36 KiB
Java
863 lines
36 KiB
Java
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);
|
||
}
|
||
});
|
||
}
|
||
});
|
||
}
|
||
}
|