/*
Copyright 2012 Jan Ove Saltvedt
This file is part of KBot.
KBot is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
KBot is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with KBot. If not, see <http://www.gnu.org/licenses/>.
*/
package com.kbotpro.scriptsystem.input;
import com.kbotpro.scriptsystem.input.internal.mouse.EventFactory;
import com.kbotpro.scriptsystem.input.jobs.MouseHoverJob;
import com.kbotpro.scriptsystem.input.jobs.MouseJob;
import com.kbotpro.scriptsystem.input.callbacks.MouseMoveListener;
import com.kbotpro.scriptsystem.various.KTimer;
import com.kbotpro.scriptsystem.various.ModuleConnector;
import com.kbotpro.scriptsystem.interfaces.MouseTarget;
import com.kbotpro.scriptsystem.interfaces.Targetable;
import com.kbotpro.bot.BotEnvironment;
import com.kbotpro.ui.BotPanel;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.util.*;
import java.util.List;
/**
* Class to supply mouse jobs and quick similar
*/
public class Mouse extends ModuleConnector {
public List<MouseJob> mouseJobs = Collections.synchronizedList(new ArrayList<MouseJob>());
private Double defaultSpeed = 1.0D;
public Mouse(BotEnvironment botEnv) {
super(botEnv);
}
/**
* Creates a MouseHoverJob with the given callback and target
* @param callback The callback
* @param target The target
* @return The created mouse job, you have to start it manually
*/
public MouseHoverJob createMouseHoverJob(MouseMoveListener callback, MouseTarget target){
MouseHoverJob job = new MouseHoverJob(new EventFactory(botEnv), botEnv, callback, target);
job.setSpeedMultiplier(defaultSpeed);
return job;
}
/**
* Creates a MouseHoverJob with the given callback and target
* @param callback The callback
* @param targetable The target
* @return The created mouse job, you have to start it manually
*/
public MouseHoverJob createMouseHoverJob(MouseMoveListener callback, Targetable targetable){
return createMouseHoverJob(callback, targetable.getTarget());
}
/**
* Creates a MouseHoverJob with the given callback and target
* @param callback The callback
* @param target The target
* @param runTime KTimer containing how long the job should run
* @return The created mouse job, you have to start it manually
*/
public MouseHoverJob createMouseHoverJob(MouseMoveListener callback, MouseTarget target, KTimer runTime){
MouseHoverJob job = new MouseHoverJob(new EventFactory(botEnv), botEnv, callback, target);
job.setTimeLimit(runTime);
job.setSpeedMultiplier(defaultSpeed);
return job;
}
/**
* Creates a MouseHoverJob with the given callback and target
* @param callback The callback
* @param targetable The target
* @param runTime KTimer containing how long the job should run
* @return The created mouse job, you have to start it manually
*/
public MouseHoverJob createMouseHoverJob(MouseMoveListener callback, Targetable targetable, KTimer runTime){
return createMouseHoverJob(callback, targetable.getTarget(), runTime);
}
/**
* Moves the mouse to the screen position and clicks the mouse if told so.
* @param x the x screen position
* @param y the y screen position
* @param click Boolean, if this is true the bot will click after reaching the target.
* @param button true = left mouse button, false = right mouse button
*/
public synchronized void moveMouse(final int x, final int y, final boolean click, final boolean button) {
MouseTarget mouseTarget = new MouseTarget() {
public Point get() {
return new Point(x, y);
}
public boolean isOver(int posX, int posY) {
return posX > x-1 && posX < x+1 && posY > y-1 && posY < y+1;
}
};
MouseHoverJob mouseHoverJob = createMouseHoverJob(new MouseMoveListener() {
int count = 0;
public void onMouseOverTarget(MouseJob mouseJob) {
if(!click){
mouseJob.stop();
return;
}
else{
count++;
if(count > random(3, 16)){
mouseJob.stop();
mouseJob.doMouseClick(button);
return;
}
}
}
public void onFinished(MouseJob mouseJob) {
}
}, mouseTarget);
mouseHoverJob.start();
mouseHoverJob.join();
}
/**
* Moves the mouse to the screen position given.
* @param x the x screen position
* @param y the y screen position
*/
public void moveMouse(final int x, final int y) {
moveMouse(x, y, false, false);
}
/**
* Moves the mouse to the screen position and clicks the mouse btton given.
* @param p The screen point to move to
* @param button true = left mouse button, false = right mouse button
*/
public void moveMouse(Point p, final boolean button) {
moveMouse(p.x, p.y, true, button);
}
/**
* Moves the mouse to the screen position and clicks the mouse btton given.
* @param p The screen point to move to
*/
public void moveMouse(Point p) {
moveMouse(p.x, p.y);
}
/**
* Moves the mouse to a point inside a rectangle
* @param r The rectangle to move the mouse to
*/
public void moveMouse(Rectangle r) {
moveMouse(r.x + random(0, r.width), r.y + random(0, r.height));
}
/**
* VERY Human like method - great for anti bans!
* This will move the mouse around the screen at a random distance between
* 1 and maxDistance, but will sometimes move it more than one, like a human
* would, resulting in cool effects like cursor circling and more.
*
* @param maxDistance
* @return true if it is going to call on itself again, false otherwise
* (returns false to you every time)
*/
public boolean moveMouseRandomly(int maxDistance) {
if (maxDistance == 0) {
return false;
}
maxDistance = random(1, maxDistance);
Point p = new Point(getRandomMouseX(maxDistance), getRandomMouseY(maxDistance));
if (p.x < 1 || p.y < 1) {
p.x = p.y = 1;
}
moveMouse(p.x, p.y);
return random(0, 2) != 0 && moveMouseRandomly(maxDistance / 2);
}
/**
* Gives a X position on the screen within the maxDistance.
*
* @param maxDistance the maximum distance the cursor will move on the X axis
* @return A random int that represents a X coordinate for the
* moveMouseRandomly method.
*/
private int getRandomMouseX(int maxDistance) {
Point p = getMousePos();
if (random(0, 2) == 0) {
return p.x - random(0, p.x < maxDistance ? p.x : maxDistance);
} else {
return p.x + random(1, (762 - p.x < maxDistance) ? 762 - p.x : maxDistance);
}
}
/**
* Gives a Y position on the screen within the maxDistance.
*
* @param maxDistance the maximum distance the cursor will move on the Y axis
* @return A random int that represents a Y coordinate for the
* moveMouseRandomly method.
*/
private int getRandomMouseY(int maxDistance) {
Point p = getMousePos();
if (random(0, 2) == 0) {
return p.y - random(0, p.y < maxDistance ? p.y : maxDistance);
} else {
return p.y + random(1, (500 - p.y < maxDistance) ? 500 - p.y : maxDistance);
}
}
/**
* Gets the mouse position
*
* @return Point with coords.
*/
public Point getMousePos() {
return botEnv.game.getMousePos();
}
/**
* Makes the mouse click the given button.
* @param button
*/
public void clickMouse(boolean button) {
EventFactory eventFactory = new EventFactory(botEnv);
Point point = getMousePos();
MouseEvent mouseEvent = eventFactory.createMousePress(point.x, point.y, button);
dispatchEvent(mouseEvent);
sleep(50, 100);
mouseEvent = eventFactory.createMouseRelease(point.x, point.y, button);
dispatchEvent(mouseEvent);
mouseEvent = eventFactory.createMouseClicked(point.x, point.y, button);
dispatchEvent(mouseEvent);
}
/**
* Moves the mouse to the start point, presses the mouse, moves to the destination and releases.
* @param startPoint
* @param destPoint
*/
public void clickAndDragMouse(Point startPoint, final Point destPoint) {
EventFactory eventFactory = new EventFactory(botEnv);
MouseTarget mouseTarget = new MouseTarget() {
public Point get() {
return new Point(destPoint.x, destPoint.y);
}
public boolean isOver(int posX, int posY) {
return posX > destPoint.x-1 && posX < destPoint.x+1 && posY > destPoint.y-1 && posY < destPoint.y+1;
}
};
if (!getMousePos().equals(startPoint)) {
moveMouse(startPoint);
}
MouseEvent mouseEvent = eventFactory.createMousePress(startPoint.x, startPoint.y, true);
botEnv.dispatchEvent(mouseEvent);
sleep(50, 80);
MouseHoverJob mouseHoverJob = createMouseHoverJob(new MouseMoveListener() {
int count = 0;
public void onMouseOverTarget(MouseJob mouseJob) {
count++;
if(count > random(3, 16)){
mouseJob.stop();
return;
}
}
public void onFinished(MouseJob mouseJob) {
}
}, mouseTarget);
mouseHoverJob.setDrag(true);
mouseHoverJob.start();
mouseHoverJob.join();
sleep(50, 100);
mouseEvent = eventFactory.createMouseRelease(destPoint.x, destPoint.y, true);
botEnv.dispatchEvent(mouseEvent);
}
/**
* Only returns if the mouse is being pressed by the bot, not by user input. Use isMousePressed() instead.
*/
public boolean mousePressed = false;
/**
* @return Returns true if the mouse is being held down by either the bot or the user.
*/
public boolean isMousePressed() {
return mousePressed || ((BotPanel.BotAppletPanel)botEnv.botPanel.botAppletPanel).mousePressed;
}
private void dispatchEvent(MouseEvent mouseEvent) {
if (mouseEvent.getID() == MouseEvent.MOUSE_PRESSED) {
mousePressed = true;
} else if (mouseEvent.getID() == MouseEvent.MOUSE_RELEASED) {
mousePressed = false;
}
botEnv.dispatchEvent(mouseEvent);
}
public synchronized void pauseAllJobs(){
for(MouseJob mouseJob: mouseJobs){
if(mouseJob.isAlive()){
mouseJob.pause();
}
}
}
public synchronized void resumeAllJobs(){
for(MouseJob mouseJob: mouseJobs){
if(mouseJob.isPaused()){
mouseJob.resume();
}
}
}
public synchronized void stopAllJobs() {
for(MouseJob mouseJob: mouseJobs){
if (mouseJob.isAlive()) {
mouseJob.cancel();
}
}
}
public boolean isMouseActive() {
for(MouseJob mouseJob: mouseJobs){
if(mouseJob.isAlive() && !mouseJob.isPaused()){
return true;
}
}
return false;
}
/**
* Internal method, don't use.
* @param mouseJob
*/
public void removeMouseJobInternally(MouseJob mouseJob) {
mouseJobs.remove(mouseJob);
}
/**
* Internal method, don't use.
* @param mouseJob
*/
public void addMouseJobInternally(MouseJob mouseJob) {
mouseJobs.add(mouseJob);
}
/**
* Gets the default mouse speed.
* 1 is normal.
* 2 is double acceleration
* @return
*/
public Double getDefaultSpeed() {
return defaultSpeed;
}
/**
* Sets the default mouse speed.
* 1 is normal.
* 2 is double acceleration
* @param defaultSpeed
*/
public void setDefaultSpeed(Double defaultSpeed) {
this.defaultSpeed = defaultSpeed;
}
}