Compare commits
32 Commits
Author | SHA1 | Date |
---|---|---|
MrBesen | 8431ace7ef | |
MrBesen | 569d3aaf81 | |
mrbesen | d75a454981 | |
MrBesen | 1b1dff4799 | |
mrbesen | 487a263fc0 | |
mrbesen | 07c134f7c6 | |
mrbesen | dc208dbca5 | |
mrbesen | 2c3ec47e3f | |
mrbesen | d2ce629dbb | |
mrbesen | cf742dd451 | |
mrbesen | c276e463a2 | |
mrbesen | da8216d521 | |
mrbesen | 963af8b78e | |
mrbesen | 72654bafff | |
mrbesen | 9fae8551fe | |
mrbesen | 515301deda | |
mrbesen | 756924f1b7 | |
mrbesen | 724d5c51ea | |
mrbesen | ae521ece46 | |
mrbesen | 2ba3e835ca | |
mrbesen | 08a2cbbd1d | |
mrbesen | e56a4ad984 | |
MrBesen | 6e64908889 | |
MrBesen | cac0badda7 | |
mrbesen | 2a96c81786 | |
MrBesen | e1bbcc0a77 | |
mrbesen | 9f585fd51d | |
mrbesen | 5ac413bd26 | |
MrBesen | 595282487c | |
MrBesen | b5c610a2ed | |
MrBesen | d2db04ba3b | |
MrBesen | 207789595f |
|
@ -2,4 +2,6 @@
|
|||
export.jardesc
|
||||
.project
|
||||
.classpath
|
||||
.profile
|
||||
.profile
|
||||
/default.profile
|
||||
target/
|
||||
|
|
27
README.md
27
README.md
|
@ -1,15 +1,34 @@
|
|||
# ClashRoyale-Bot
|
||||
A Bot, that controls ClashRoyal. Perfect for Crown farming.
|
||||
|
||||
###### How to use it?
|
||||
# Warning ! You might get banned for useing this Program.
|
||||
And you going to loose some trophys.
|
||||
Bot losses some matches -> Bot gets easyer oponents -> Bot winns some matches (And earn crowns) -> Bot gets harder oponents -> Bot looses some matches....
|
||||
### What is this bot?
|
||||
* Automated Bot for Battles
|
||||
* funny to watch
|
||||
* Good for Crown-farming for the clan chest
|
||||
|
||||
### What is this bot not?
|
||||
* A way to farm trophys
|
||||
* A Programm that plays better than an average human
|
||||
* Time efficent
|
||||
|
||||
|
||||
## Download
|
||||
[Download](http://github.com/mrbesen/clashroyale-bot/releases/)
|
||||
|
||||
#### How to use it?
|
||||
This java Apllication needs some kind of Mobile Device Emulator or Interface.
|
||||
I have tested it with Teamviewer and Nox Appplayer. You can configure points of the Clashroyale app, where the bot automatically clicks.
|
||||
These clicks can cause Troops to spawn or Buttons to be Pressed.
|
||||
## Video (a bit outdated):
|
||||
[![Video](https://i.vimeocdn.com/video/641445132_640.jpg)](https://vimeo.com/222811186 "Video")
|
||||
|
||||
###### How does it work?
|
||||
This program emulates a mouse and keyboard and controls your computer with that emulated hardware. To The App it look, like you are a normal User.
|
||||
#### How does it work?
|
||||
This program emulates a mouse and keyboard and controls your computer with that emulated hardware. To The App it look, like you are a normal user.
|
||||
|
||||
##### Features:
|
||||
#### Features:
|
||||
* Automated Backfocus
|
||||
* Save / Load Profiles
|
||||
* Pause or Skip Actions
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>de.mrbesen</groupId>
|
||||
<artifactId>clashroyalebot</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<name>clashroyalebot</name>
|
||||
<url>http://maven.apache.org</url>
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
</properties>
|
||||
<dependencies>
|
||||
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<descriptorRefs>
|
||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||
</descriptorRefs>
|
||||
<archive>
|
||||
<manifest>
|
||||
<mainClass>de.mrbesen.cr.auto.clicker.Main</mainClass>
|
||||
</manifest>
|
||||
<manifestEntries>
|
||||
<Class-Path>.</Class-Path>
|
||||
</manifestEntries>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
|
@ -1,4 +1,4 @@
|
|||
package mrbesen.cr.auto.clicker;
|
||||
package de.mrbesen.cr.auto.clicker;
|
||||
|
||||
import java.awt.AWTException;
|
||||
import java.awt.Color;
|
||||
|
@ -34,24 +34,31 @@ public class Clicker implements Runnable{
|
|||
private int randomness = 15;
|
||||
private boolean paused = false;
|
||||
private boolean backfocus = false;
|
||||
private final int waittime = 50;//time between mouse teleports and clicks
|
||||
private final int waittime = 250;//time between mouse teleports and clicks
|
||||
|
||||
private int mincolordistance = 35;
|
||||
private Overlay ov = null;
|
||||
|
||||
OSType os;
|
||||
private int alt_key;
|
||||
|
||||
long started = -1;
|
||||
|
||||
private void sleep( int ms) {
|
||||
//update ui
|
||||
Main.get().ui.printTime((int) ( (System.currentTimeMillis()-started) / 1000 ));
|
||||
|
||||
if(skipbattle)
|
||||
return;
|
||||
try {
|
||||
Thread.sleep(ms);
|
||||
while(paused) {
|
||||
if(ms > 1000) {
|
||||
Thread.sleep(1000);//split the sleep time.
|
||||
sleep(ms-1000);
|
||||
} else
|
||||
Thread.sleep(ms);
|
||||
while(paused & should_run) {
|
||||
Thread.sleep(75);
|
||||
}
|
||||
} catch (InterruptedException e) {//when skip is applyed
|
||||
;
|
||||
}
|
||||
} catch (InterruptedException e) { } //when skip is applyed, or the bot gets stopped
|
||||
}
|
||||
|
||||
public void start() {
|
||||
|
@ -60,11 +67,13 @@ public class Clicker implements Runnable{
|
|||
running = true;
|
||||
thread = new Thread(this, "BOT");
|
||||
thread.start();
|
||||
started = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
should_run = false;
|
||||
skipbattle = true;
|
||||
while(running) {
|
||||
thread.interrupt();//stop that shit (its maybe sleeping)
|
||||
}
|
||||
|
@ -85,21 +94,15 @@ public class Clicker implements Runnable{
|
|||
public void run() {
|
||||
sleep(1000);//chill ma
|
||||
|
||||
//determine os
|
||||
String oss = System.getProperty("os.name").toLowerCase();
|
||||
if(oss.contains("nix") | oss.contains("nux") | oss.contains("aix"))
|
||||
os = OSType.Linux;
|
||||
else if(oss.contains("win"))
|
||||
os = OSType.Windows;
|
||||
else if(oss.contains("mac"))
|
||||
os = OSType.OSX;
|
||||
else
|
||||
Main.get().ui.info("OS not supported for backfocus: " + oss);
|
||||
|
||||
alt_key = ( oss.contains("nix") | oss.contains("nux") | oss.contains("aix") | oss.contains("win") ? KeyEvent.VK_ALT : KeyEvent.VK_META);
|
||||
//windows and linux have another alt key than mac, so lets determine the OS type, to determine the key code.
|
||||
|
||||
int card = 0;
|
||||
try {
|
||||
Robot rob = new Robot();
|
||||
while(should_run) {
|
||||
Main.get().ui.info("Starting Battle.");
|
||||
sleep(500);
|
||||
clickL(rob, battle);//smash the start button
|
||||
sleep(1000);
|
||||
|
@ -107,11 +110,11 @@ public class Clicker implements Runnable{
|
|||
backfocus(rob);
|
||||
//battle is starting up
|
||||
sleep(9000);//wait for the battle to start (loading screen)
|
||||
Main.get().ui.info("Battle started.");
|
||||
inbattle = true;
|
||||
float modifier = 1;
|
||||
long start = System.currentTimeMillis();
|
||||
long lastwait = start;//actions like moving mouse and do stuff gets messured and subtracted of the wait's
|
||||
Main.get().ui.info("Battle begins.");
|
||||
while( ((System.currentTimeMillis() - start) / 6000) < 41 & should_run & !skipbattle) {
|
||||
|
||||
//check für ok-button
|
||||
|
@ -141,8 +144,8 @@ public class Clicker implements Runnable{
|
|||
modifier = 1.5f;
|
||||
// eingestellter wert (0.1 sec) ggf. durch 2 teilen vergangene zeit abziehen (zeit fürs setztem der letzten truppen)
|
||||
int waittime = ( (int) (((truppenwait * 100) / modifier) - (System.currentTimeMillis()- lastwait)) );//how long to wait?
|
||||
Main.get().ui.info("Waiting for: " + waittime);
|
||||
while (waittime > 1500 & !skipbattle) {//check for the ok-button every 3 seconds
|
||||
Main.get().ui.info("Waiting for: " + (waittime / 1000) + "s");
|
||||
while (waittime > 1500 & !skipbattle & should_run) {//check for the ok-button every 3 seconds
|
||||
long startwait = System.currentTimeMillis();//record needed time
|
||||
if(checkOK(end, rob, ok_button)) {//check
|
||||
Main.get().ui.info("OK-button detected!");
|
||||
|
@ -161,13 +164,13 @@ public class Clicker implements Runnable{
|
|||
clickL(rob, end);//ok button
|
||||
backfocus(rob);
|
||||
Main.get().ui.info("Battle ended.");
|
||||
sleep(9000);//9 sec-loading screen
|
||||
sleep(7000);//7 sec-loading screen
|
||||
//checken, ob Arena wechsel pop-up
|
||||
while(checkOK(arena_switch, rob,arena_view)) {
|
||||
System.out.println("Arena found, clicking");
|
||||
while(checkOK(arena_switch, rob,arena_view) & should_run) {
|
||||
Main.get().ui.info("Arena found, clicking");
|
||||
clickL(rob, arena_switch);
|
||||
backfocus(rob);
|
||||
sleep(2000);
|
||||
sleep(2000);//wait 2 seconds
|
||||
}
|
||||
}
|
||||
} catch (AWTException e) {
|
||||
|
@ -199,18 +202,14 @@ public class Clicker implements Runnable{
|
|||
|
||||
private void backfocus(Robot bot) {
|
||||
if(backfocus) {
|
||||
if(os == OSType.Windows | os == OSType.Linux)
|
||||
bot.keyPress(KeyEvent.VK_ALT);
|
||||
else//osx / unsupported
|
||||
bot.keyPress(KeyEvent.VK_META);
|
||||
|
||||
|
||||
bot.keyPress(alt_key);
|
||||
|
||||
bot.keyPress(KeyEvent.VK_TAB);
|
||||
sleep(waittime);
|
||||
bot.keyRelease(KeyEvent.VK_TAB);
|
||||
if(os == OSType.Windows | os == OSType.Linux)
|
||||
bot.keyRelease(KeyEvent.VK_ALT);
|
||||
else//osx / unsupported
|
||||
bot.keyRelease(KeyEvent.VK_META);
|
||||
|
||||
bot.keyRelease(alt_key);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -278,18 +277,26 @@ public class Clicker implements Runnable{
|
|||
return (end != null & battle != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a Leftclick.
|
||||
* @param b the Robot to use
|
||||
* @param a the Position to click
|
||||
*/
|
||||
private void clickL(Robot b, Point a) {
|
||||
if(!should_run)
|
||||
return;
|
||||
Point old = getMouse();
|
||||
b.mouseMove(a.x, a.y);
|
||||
sleep(50);
|
||||
sleep(waittime);
|
||||
clickL(b);
|
||||
sleep(50);
|
||||
b.mouseMove(old.x, old.y);
|
||||
sleep(50);
|
||||
sleep(waittime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a Leftclick
|
||||
* @param b
|
||||
*/
|
||||
private void clickL(Robot b) {//40 ms delay
|
||||
b.mousePress(InputEvent.BUTTON1_MASK);
|
||||
sleep(waittime);
|
||||
|
@ -315,22 +322,22 @@ public class Clicker implements Runnable{
|
|||
return false;
|
||||
//long start = System.currentTimeMillis();
|
||||
int count = 0;
|
||||
BufferedImage img = bot.createScreenCapture(new Rectangle(p.x-10, p.y-10, 20, 20));//smile
|
||||
for (int x = 0; x < 20; x++) {
|
||||
for (int y = 0; y < 20; y++) {
|
||||
BufferedImage img = bot.createScreenCapture(getRect(p.x, p.y));//smile
|
||||
for (int x = 0; x < img.getWidth(); x++) {
|
||||
for (int y = 0; y < img.getHeight(); y++) {
|
||||
int color = img.getRGB(x, y);
|
||||
int red = (color & 0x00ff0000) >> 16;
|
||||
int green = (color & 0x0000ff00) >> 8;
|
||||
int blue = color & 0x000000ff;
|
||||
double distance = Math.sqrt(Math.pow((blue - goalcolor.getBlue()), 2)
|
||||
int green = (color & 0x0000ff00) >> 8;
|
||||
int blue = color & 0x000000ff;
|
||||
double distance = Math.sqrt(Math.pow((blue - goalcolor.getBlue()), 2)
|
||||
+ Math.pow((red - goalcolor.getRed()), 2) + Math.pow((green - goalcolor.getGreen()), 2));//calculate the distance between the goalcolor and the test color
|
||||
if (distance < mincolordistance)
|
||||
count++;
|
||||
if (distance < mincolordistance)
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
// System.out.println("counts: " + count);//some performance checking
|
||||
return count > 70;
|
||||
System.out.println("counts: " + count);//some performance checking
|
||||
return count > 4;//engough pixel have the right color
|
||||
}
|
||||
|
||||
public Point getMouse() {
|
||||
|
@ -366,7 +373,7 @@ public class Clicker implements Runnable{
|
|||
arena_view = c;
|
||||
break;
|
||||
}
|
||||
if(mincolordistance < minimumdistance)
|
||||
if(mincolordistance < minimumdistance)//enlarging mindistance
|
||||
mincolordistance = minimumdistance;
|
||||
System.out.println(colornum + ": "+c.getRed() + " " + c.getGreen() + " " + c.getBlue());
|
||||
}
|
||||
|
@ -380,10 +387,23 @@ public class Clicker implements Runnable{
|
|||
paused = b;
|
||||
}
|
||||
|
||||
private enum OSType {
|
||||
Linux,
|
||||
Windows,
|
||||
OSX,
|
||||
unsupported
|
||||
public static Rectangle getRect(int x, int y) {
|
||||
return new Rectangle(x-2, y-2, 5, 5);
|
||||
}
|
||||
|
||||
public void toggleOverlay() {
|
||||
if(ov == null) {
|
||||
try {
|
||||
ov = new Overlay();
|
||||
ov.set(playout, cardslots, end, battle, arena_switch);
|
||||
ov.init();
|
||||
} catch(Exception e) {
|
||||
System.out.println("Catched Exception, while inflateing Overlay: ");
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
ov.close();
|
||||
ov = null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package mrbesen.cr.auto.clicker;
|
||||
package de.mrbesen.cr.auto.clicker;
|
||||
|
||||
public class Main {
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
package de.mrbesen.cr.auto.clicker;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics;
|
||||
|
||||
import javax.swing.JFrame;
|
||||
|
||||
public class Overlay {
|
||||
|
||||
JFrame frame;
|
||||
Point spawn;
|
||||
Point cards[];
|
||||
Point ok;
|
||||
Point battle;
|
||||
Point arenaview;
|
||||
|
||||
public Overlay() {
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if(frame != null) {
|
||||
frame.dispose();
|
||||
}
|
||||
}
|
||||
}, "Shutdownhook-Overlaycloser"));
|
||||
}
|
||||
|
||||
void set(Point spawn, Point[] cards, Point ok, Point battle, Point arenaview) {
|
||||
this.spawn = spawn;
|
||||
this.cards = cards;
|
||||
this.ok = ok;
|
||||
this.battle = battle;
|
||||
this.arenaview = arenaview;
|
||||
}
|
||||
|
||||
public void init() {
|
||||
frame = new JFrame("Bot Overlay");
|
||||
frame.setUndecorated(true);
|
||||
frame.setOpacity(0.5f);
|
||||
|
||||
int width=0, height=0;
|
||||
int x=spawn.x,y=spawn.y;
|
||||
for(Point p : getlist()) {
|
||||
if(p != null) {
|
||||
if(p.x < x) {
|
||||
width += (x-p.x);//umsoviel weiter machen, wie nach links verschoben wird
|
||||
x = p.x;
|
||||
}
|
||||
if(x+width < p.x) {
|
||||
width += x+width-p.x;
|
||||
}
|
||||
if(p.y < y) {
|
||||
height += (y-p.y);
|
||||
y = p.y;
|
||||
}
|
||||
if(y+height < p.y) {
|
||||
height += y+height-p.y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
frame.setSize(width, height);
|
||||
frame.setLocation(x, y);
|
||||
|
||||
frame.setVisible(true);
|
||||
|
||||
Graphics gra = frame.getGraphics();
|
||||
gra.setColor(new Color(255, 0, 0));//red
|
||||
for(Point p : cards) {
|
||||
if(p != null) {
|
||||
gra.drawRect(p.x-1, p.y-1, 300, 300);
|
||||
}
|
||||
}
|
||||
System.out.println("Overlay is da!");
|
||||
}
|
||||
|
||||
public void close() {
|
||||
frame.dispose();
|
||||
}
|
||||
|
||||
|
||||
private Point[] getlist() {
|
||||
return new Point[] {spawn,ok,battle,arenaview, cards[0],cards[1],cards[2],cards[3]};
|
||||
}
|
||||
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package mrbesen.cr.auto.clicker;
|
||||
package de.mrbesen.cr.auto.clicker;
|
||||
|
||||
import java.util.Random;
|
||||
|
|
@ -1,8 +1,7 @@
|
|||
package mrbesen.cr.auto.clicker;
|
||||
package de.mrbesen.cr.auto.clicker;
|
||||
|
||||
import java.awt.AWTException;
|
||||
import java.awt.Color;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Robot;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.Comparator;
|
||||
|
@ -24,14 +23,14 @@ public class PosColSelector extends PosSelector {
|
|||
try {
|
||||
Robot rob = new Robot();
|
||||
Point p = ui.bot.getMouse();
|
||||
BufferedImage img = rob.createScreenCapture(new Rectangle(p.x-10, p.y-10, 20, 20));
|
||||
BufferedImage img = rob.createScreenCapture(Clicker.getRect(p.x, p.y));
|
||||
//calculate avg color;
|
||||
int red = 0;
|
||||
int green = 0;
|
||||
int blue = 0;
|
||||
int count = 0;
|
||||
for (int x = 0; x < 20; x++) {
|
||||
for (int y = 0; y < 20; y++) {
|
||||
for (int x = 0; x < img.getWidth(); x++) {
|
||||
for (int y = 0; y < img.getHeight(); y++) {
|
||||
int color = img.getRGB(x, y);
|
||||
red += (color & 0x00ff0000) >> 16;
|
||||
green += (color & 0x0000ff00) >> 8;
|
||||
|
@ -46,8 +45,8 @@ public class PosColSelector extends PosSelector {
|
|||
|
||||
//calculate distances:
|
||||
List<Integer> dist = new LinkedList<Integer>();
|
||||
for (int x = 0; x < 20; x++) {
|
||||
for (int y = 0; y < 20; y++) {
|
||||
for (int x = 0; x < img.getWidth(); x++) {
|
||||
for (int y = 0; y < img.getHeight(); y++) {
|
||||
int color = img.getRGB(x, y);
|
||||
int redf = (color & 0x00ff0000) >> 16;
|
||||
int greenf = (color & 0x0000ff00) >> 8;
|
||||
|
@ -72,7 +71,7 @@ public class PosColSelector extends PosSelector {
|
|||
}
|
||||
});
|
||||
|
||||
int miniumdistance = dist.get(150);//at least the first 100 tests should fit
|
||||
int miniumdistance = dist.get((int) (dist.size()*0.3f));//at least the first third tests should fit
|
||||
// int maximumdistance = dist.get(dist.size()-1);
|
||||
System.out.println("minimum distance: " + miniumdistance );
|
||||
ui.bot.setColor(c,colornum, miniumdistance);
|
|
@ -1,4 +1,4 @@
|
|||
package mrbesen.cr.auto.clicker;
|
||||
package de.mrbesen.cr.auto.clicker;
|
||||
|
||||
import java.awt.Color;
|
||||
|
||||
|
@ -11,6 +11,7 @@ public class PosSelector implements Runnable {
|
|||
UI ui;
|
||||
private boolean required;
|
||||
|
||||
|
||||
public boolean isRequired() {
|
||||
return required;
|
||||
}
|
||||
|
@ -24,6 +25,7 @@ public class PosSelector implements Runnable {
|
|||
|
||||
@Override
|
||||
public void run() {
|
||||
button.setBackground(Color.MAGENTA);
|
||||
try {
|
||||
for(int i = 5; i > 0; i--) {//countdown
|
||||
ui.info(i + "");
|
|
@ -1,6 +1,7 @@
|
|||
package mrbesen.cr.auto.clicker;
|
||||
package de.mrbesen.cr.auto.clicker;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.File;
|
||||
|
@ -9,19 +10,21 @@ import java.io.IOException;
|
|||
import java.math.BigDecimal;
|
||||
import java.util.Scanner;
|
||||
|
||||
import javax.swing.Box;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuBar;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JSlider;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
|
||||
import com.sun.istack.internal.Nullable;
|
||||
import javax.swing.filechooser.FileNameExtensionFilter;
|
||||
|
||||
public class UI implements ActionListener {
|
||||
|
||||
|
@ -31,13 +34,15 @@ public class UI implements ActionListener {
|
|||
|
||||
private JPanel root = new JPanel();
|
||||
private JPanel top = new JPanel();
|
||||
private JPanel middle = new JPanel();
|
||||
private JPanel sliderpanel = new JPanel();
|
||||
private JPanel bottom = new JPanel();
|
||||
//JPanel slider = new JPanel();
|
||||
|
||||
private JMenuBar menubar = new JMenuBar();
|
||||
private JMenu file_ = new JMenu("File");
|
||||
private JMenuItem load = new JMenuItem();
|
||||
private JMenuItem save = new JMenuItem();
|
||||
private JMenuItem new_ = new JMenuItem();
|
||||
|
||||
private AutoPlayBox autoplay = new AutoPlayBox();
|
||||
private JCheckBox doubleplace = new JCheckBox("DoublePlace");
|
||||
|
@ -58,9 +63,13 @@ public class UI implements ActionListener {
|
|||
private JButton skip = new JButton("SKIP"); // the button, to skip waiting
|
||||
private JButton pause = new JButton("Pause");
|
||||
private JButton exit = new JButton("EXIT");
|
||||
private JButton overlay = new JButton("Overlay[Experimental]");
|
||||
|
||||
private JLabel info = new JLabel("Define positions, to start.");
|
||||
private JLabel time = new JLabel("0 s");
|
||||
|
||||
private JFileChooser filechooser = new JFileChooser();
|
||||
|
||||
private Slider[] slider = {
|
||||
new Slider("Waittime: ","s", 1,300,180,-1, null, new Updater() {
|
||||
@Override
|
||||
|
@ -78,21 +87,23 @@ public class UI implements ActionListener {
|
|||
|
||||
Clicker bot = new Clicker();
|
||||
|
||||
private File file = new File(".profile");
|
||||
|
||||
public UI() {
|
||||
Main.get().ui = this;
|
||||
|
||||
//init screen
|
||||
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
|
||||
frame.setSize(730, 180);
|
||||
frame.setSize(830,( System.getProperty("os.name").toLowerCase().contains("win") ? 220 : 180));//extra large for windows
|
||||
|
||||
save.setText("Save");
|
||||
save.addActionListener(this);
|
||||
load.setText("Load");
|
||||
load.addActionListener(this);
|
||||
new_.setText("New");
|
||||
new_.addActionListener(this);
|
||||
|
||||
file_.add(save);
|
||||
file_.add(load);
|
||||
file_.add(new_);
|
||||
menubar.add(file_);
|
||||
frame.setJMenuBar(menubar);
|
||||
|
||||
|
@ -106,33 +117,62 @@ public class UI implements ActionListener {
|
|||
start.addActionListener(this);
|
||||
pause.addActionListener(this);
|
||||
exit.addActionListener(this);
|
||||
overlay.addActionListener(this);
|
||||
doubleplace.addActionListener(this);
|
||||
backfocus.addActionListener(this);
|
||||
|
||||
for(PosSelector poss : posselctors) {
|
||||
for(PosSelector poss : posselctors) {//construct PosSelector Panel
|
||||
top.add(poss.button);
|
||||
}
|
||||
|
||||
bottom.add(start);
|
||||
bottom.add(skip);
|
||||
bottom.add(pause);
|
||||
bottom.add(exit);
|
||||
bottom.add(autoplay);
|
||||
bottom.add(doubleplace);
|
||||
bottom.add(backfocus);
|
||||
|
||||
root.add(top);
|
||||
middle.add(start);//construct button paneö
|
||||
middle.add(skip);
|
||||
middle.add(pause);
|
||||
middle.add(exit);
|
||||
//middle.add(overlay);//added later
|
||||
middle.add(autoplay);
|
||||
middle.add(doubleplace);
|
||||
middle.add(backfocus);
|
||||
|
||||
for(Slider s : slider) {//construct slider panel
|
||||
sliderpanel.add(s);
|
||||
}
|
||||
|
||||
bottom.add(info);//construct bottom panel
|
||||
bottom.add(Box.createRigidArea(new Dimension(150, 5)));
|
||||
bottom.add(time);
|
||||
|
||||
root.add(top);//add every pannel
|
||||
root.add(middle);
|
||||
root.add(sliderpanel);
|
||||
root.add(bottom);
|
||||
|
||||
root.add(info);
|
||||
|
||||
for(Slider s : slider) {
|
||||
root.add(s);
|
||||
}
|
||||
|
||||
frame.add(root);
|
||||
|
||||
frame.add(root);//create frame
|
||||
frame.setVisible(true);
|
||||
|
||||
//set tooltips
|
||||
start.setToolTipText("Starts the Bot. (When gray, try to set the positions for the red buttons!)");
|
||||
skip.setToolTipText("Skips the current Action.(Waiting or beeing in a match, only usefull, when the bot miss clicked somewhere)");
|
||||
pause.setToolTipText("Pauses the \"output\" of the Bot, but the internal states are still updated.");
|
||||
exit.setToolTipText("Stops the Bot and closes the Window.");
|
||||
overlay.setToolTipText("Enables a Overlay to visualize where the Bot trys to click.");
|
||||
autoplay.setToolTipText("Enable or disable auto placement of cards.");
|
||||
doubleplace.setToolTipText("Everytime the bot wants to play a card, he trys to play two cards at once.");
|
||||
backfocus.setToolTipText("After each mouseclickaction the bot tryes to give the old window the focus back.");
|
||||
slider[0].setToolTipText("the time the Bot waits between two crads.");
|
||||
slider[1].setToolTipText("Give a value, how offset the playout place should be, to look more like a human player to the opponent and the game itself.");
|
||||
|
||||
posselctors[0].button.setToolTipText("Set the position for the \"Battle\"-Button.");
|
||||
posselctors[1].button.setToolTipText("Set the position for the \"ok\"-Button at the end of a match. Be carefull, this also saves the color of the button to auto-detect it.");
|
||||
posselctors[2].button.setToolTipText("Set the Position of Card 1");
|
||||
posselctors[3].button.setToolTipText("Set the Position of Card 2");
|
||||
posselctors[4].button.setToolTipText("Set the Position of Card 3");
|
||||
posselctors[5].button.setToolTipText("Set the Position of Card 4");
|
||||
posselctors[6].button.setToolTipText("Set the Position, where a Card should be placed. Leave it empty to use the same position as the \"Battle\" position.");
|
||||
posselctors[7].button.setToolTipText("Set the position of the Close button, of the menue that po up, when you tap the arena. This one also saves the color of the position to auto detect it.");
|
||||
|
||||
filechooser.removeChoosableFileFilter(filechooser.getAcceptAllFileFilter());
|
||||
filechooser.addChoosableFileFilter(new FileNameExtensionFilter("Botsettings", "profile"));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -167,6 +207,7 @@ public class UI implements ActionListener {
|
|||
else if(srcb.equals(exit)) {
|
||||
bot.stop();
|
||||
frame.setVisible(false);
|
||||
frame.dispose();
|
||||
System.exit(0);
|
||||
} else if(srcb.equals(pause)) {
|
||||
if(bot.isPaused()) {//the bot is going to be unpaused
|
||||
|
@ -177,13 +218,26 @@ public class UI implements ActionListener {
|
|||
info("Paused.");
|
||||
}
|
||||
bot.setPause(!bot.isPaused());
|
||||
} else if(srcb.equals(overlay)) {
|
||||
bot.toggleOverlay();
|
||||
}
|
||||
} else if(src instanceof JMenuItem) {
|
||||
JMenuItem srcI = (JMenuItem) src;
|
||||
if(srcI.equals(load)) {
|
||||
load(true);
|
||||
int returnval = filechooser.showOpenDialog(frame);
|
||||
if(returnval == JFileChooser.APPROVE_OPTION) {
|
||||
File f = filechooser.getSelectedFile();
|
||||
load(f, true);
|
||||
} else
|
||||
info("cancled.");
|
||||
} else if(srcI.equals(save)) {
|
||||
save();
|
||||
int returnval = filechooser.showOpenDialog(frame);
|
||||
if(returnval == JFileChooser.APPROVE_OPTION) {
|
||||
save(filechooser.getSelectedFile());
|
||||
} else
|
||||
info("cancled.");
|
||||
} else if(srcI.equals(new_)) {
|
||||
new_();
|
||||
}
|
||||
} else if(src instanceof JCheckBox) {
|
||||
JCheckBox srcb = (JCheckBox) src;
|
||||
|
@ -200,10 +254,10 @@ public class UI implements ActionListener {
|
|||
}
|
||||
}
|
||||
|
||||
private void load(boolean info) {
|
||||
if(file.exists()) {
|
||||
private void load(File f, boolean info) {
|
||||
if(f.exists()) {
|
||||
try {
|
||||
Scanner s = new Scanner(file);
|
||||
Scanner s = new Scanner(f);
|
||||
while(s.hasNextLine()) {
|
||||
String split[] = s.nextLine().split(" ");
|
||||
if(!split[1].equals("null")) {
|
||||
|
@ -245,12 +299,23 @@ public class UI implements ActionListener {
|
|||
info("no profile found.");
|
||||
}
|
||||
|
||||
private void save() {
|
||||
private void save(File f) {
|
||||
try {
|
||||
if(!file.exists())
|
||||
file.createNewFile();
|
||||
if(!f.getName().endsWith(".profile"))
|
||||
f = new File(f.getAbsoluteFile() + ".profile");
|
||||
if(f.exists()){
|
||||
/*ok == 0
|
||||
cancel = 2*/
|
||||
int choose = JOptionPane.showConfirmDialog(null, "You are going to override the old profile!", "Override", JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE);
|
||||
if(choose == 2) {
|
||||
info("canceled.");
|
||||
return;
|
||||
}
|
||||
|
||||
} else
|
||||
f.createNewFile();
|
||||
|
||||
FileWriter fw = new FileWriter(file);
|
||||
FileWriter fw = new FileWriter(f);
|
||||
fw.write(bot.serialize()+"\n101 "+ slider[0].getValue() + "\n102 " + doubleplace.isSelected()+"\n103 " + slider[1].getValue());
|
||||
fw.flush();
|
||||
fw.close();
|
||||
|
@ -262,6 +327,28 @@ public class UI implements ActionListener {
|
|||
}
|
||||
}
|
||||
|
||||
private void new_() {
|
||||
int choose = JOptionPane.showConfirmDialog(null, "All of your setting are going to be lost, if you dont save it.", "Settings lost", JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE);
|
||||
if(choose == 2) {
|
||||
info("canceled.");
|
||||
return;
|
||||
}
|
||||
bot.stop();
|
||||
bot = null;
|
||||
bot = new Clicker();
|
||||
|
||||
//set all buttons to red
|
||||
start.setEnabled(false);
|
||||
skip.setEnabled(false);
|
||||
for(PosSelector poss : posselctors) {
|
||||
poss.red();
|
||||
}
|
||||
|
||||
for(Slider s : slider) {
|
||||
s.reset();
|
||||
}
|
||||
}
|
||||
|
||||
public void refresh() {
|
||||
//check if all required positions are set
|
||||
// & set the colors
|
||||
|
@ -286,11 +373,67 @@ public class UI implements ActionListener {
|
|||
info.setText(a);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the time label to this time.
|
||||
* @param seconds in seconds.
|
||||
* Negative time is set to zero.
|
||||
*/
|
||||
public void printTime(int seconds) {
|
||||
if(seconds < 0)//not allowed
|
||||
seconds = 0;
|
||||
|
||||
StringBuilder out = new StringBuilder();
|
||||
|
||||
int d = 0;
|
||||
while(seconds >= 86400) {
|
||||
seconds -= 86400;
|
||||
d ++;
|
||||
}
|
||||
|
||||
if(d > 0) {
|
||||
out.append(d);
|
||||
out.append("d ");
|
||||
}
|
||||
|
||||
int h = 0;//hours
|
||||
while(seconds >= 3600) {
|
||||
seconds -= 3600;
|
||||
h ++;
|
||||
}
|
||||
|
||||
if(h > 0) {
|
||||
out.append(h);
|
||||
out.append("h ");
|
||||
}
|
||||
|
||||
int m = 0;//min
|
||||
while(seconds >= 60) {
|
||||
seconds -= 60;
|
||||
m ++;
|
||||
}
|
||||
|
||||
if(m > 0) {
|
||||
out.append(m);
|
||||
out.append("m ");
|
||||
}
|
||||
|
||||
if(seconds > 0) {
|
||||
out.append(seconds);
|
||||
out.append("s");
|
||||
}
|
||||
|
||||
if(out.length() == 0)
|
||||
out.append('-');//nothing
|
||||
|
||||
time.setText(out.toString());
|
||||
}
|
||||
|
||||
public void setPositionDone() {
|
||||
isSelectionRunning = false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public interface Updater {
|
||||
public void update(int nummber);
|
||||
}
|
||||
|
@ -326,7 +469,7 @@ public class UI implements ActionListener {
|
|||
private static final long serialVersionUID = 1L;
|
||||
private JSlider slider;
|
||||
private JLabel label;
|
||||
|
||||
private int defaultvalue;
|
||||
private ChangeListener listener;
|
||||
private Updater updater;
|
||||
private String prefix = "", sufix = "";
|
||||
|
@ -339,7 +482,7 @@ public class UI implements ActionListener {
|
|||
* @param startvalue inital value
|
||||
* @param komma 10^x offset for komma digits
|
||||
*/
|
||||
public Slider(String prefix, String sufix, int minvalue, int maxvalue, int startvalue, int komma, @Nullable ChangeListener cl,@Nullable Updater upd, boolean enabled) {//ChangeListener or Updater could be Null!
|
||||
public Slider(String prefix, String sufix, int minvalue, int maxvalue, int startvalue, int komma, ChangeListener cl, Updater upd, boolean enabled) {//ChangeListener or Updater could be Null!
|
||||
slider = new JSlider(minvalue, maxvalue, startvalue);
|
||||
slider.addChangeListener(this);
|
||||
if(prefix != null)
|
||||
|
@ -354,6 +497,7 @@ public class UI implements ActionListener {
|
|||
listener = cl;
|
||||
updater = upd;
|
||||
slider.setEnabled(enabled);
|
||||
defaultvalue = startvalue;
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
|
@ -383,5 +527,12 @@ public class UI implements ActionListener {
|
|||
if(updater != null)
|
||||
updater.update(slider.getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Restores the default value, does not change the controlled value, just the displayed one
|
||||
*/
|
||||
public void reset() {
|
||||
setValue(defaultvalue);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue