attempting to extract agent into interfaces

This commit is contained in:
dtookey 2023-08-06 17:43:54 -04:00
parent 27c155ef70
commit 8d5a8ec386
3 changed files with 70 additions and 78 deletions

View File

@ -1,4 +1,5 @@
import java.awt.Point import java.awt.Point
import java.awt.Robot
import java.awt.event.KeyEvent import java.awt.event.KeyEvent
/** /**
@ -18,7 +19,7 @@ import java.awt.event.KeyEvent
* specific workflow logic and leverage the agent for the lower level * specific workflow logic and leverage the agent for the lower level
* activities needed to craft, cook, etc. * activities needed to craft, cook, etc.
*/ */
class Agent: Doer() { class Agent(val controller: RobotController = RobotController()) {
companion object { companion object {
/** /**
@ -182,14 +183,14 @@ class Agent: Doer() {
*/ */
fun promptUserForPoint(prompt: String): Point { fun promptUserForPoint(prompt: String): Point {
println(prompt) println(prompt)
countDown(5) { controller.countDown(5) {
print("\rtaking point snapshot in $it... ") print("\rtaking point snapshot in $it... ")
if (it == 0) { if (it == 0) {
println("\r ") println("\r ")
} }
} }
return getPointerLocation() return controller.getPointerLocation()
} }
/** /**
@ -209,14 +210,14 @@ class Agent: Doer() {
* a reasonable scroll animation speed. * a reasonable scroll animation speed.
*/ */
fun scrollOutToHeight(height: Int, scrollWaitAndVariance: Long = 10L) { fun scrollOutToHeight(height: Int, scrollWaitAndVariance: Long = 10L) {
sleep(1000) controller.sleep(1000)
for (i in 0 until height * 2) { for (i in 0 until height * 2) {
scrollIn(scrollWaitAndVariance, scrollWaitAndVariance) controller.scrollIn(scrollWaitAndVariance, scrollWaitAndVariance)
} }
for (i in 0 until height) { for (i in 0 until height) {
scrollOut(scrollWaitAndVariance, scrollWaitAndVariance) controller.scrollOut(scrollWaitAndVariance, scrollWaitAndVariance)
} }
} }
@ -245,19 +246,19 @@ class Agent: Doer() {
waitDurationVariance: Long waitDurationVariance: Long
) { ) {
//open the bank located by the chest parameter //open the bank located by the chest parameter
moveMouseLeftClickAndSleep(getAlmostPoint(chest, Doer.WiggleParams()), 900, 400) controller.moveMouseLeftClickAndSleep(controller.getAlmostPoint(chest, WiggleParams()), 900, 400)
//withdraw the desired inventory preset //withdraw the desired inventory preset
keypress(bankPresetHotkey) controller.keyPress(bankPresetHotkey)
//sleep for a server tick //sleep for a server tick
sleepForNTicks(1) controller.sleepForNTicks(1)
//open the crafting dialog with the correct hotkey //open the crafting dialog with the correct hotkey
keypress(craftingDialogueHotkey) controller.keyPress(craftingDialogueHotkey)
//sleep for a server tick //sleep for a server tick
sleepForNTicks(1) controller.sleepForNTicks(1)
//press the "accept" default hotkey //press the "accept" default hotkey
keypress(KeyEvent.VK_SPACE) controller.keyPress(KeyEvent.VK_SPACE)
//wait for the desired time to finish //wait for the desired time to finish
sleep(waitDurationMillis, waitDurationVariance) controller.sleep(waitDurationMillis, waitDurationVariance)
} }
/** /**
@ -277,16 +278,16 @@ class Agent: Doer() {
*/ */
fun bankStandWithoutDialog(chest: Point, invKey: Int, hotKey: Int) { fun bankStandWithoutDialog(chest: Point, invKey: Int, hotKey: Int) {
//open the bank located by the chest parameter //open the bank located by the chest parameter
moveMouseLeftClickAndSleep(getAlmostPoint(chest, Doer.WiggleParams()), 900, 400) controller.moveMouseLeftClickAndSleep(controller.getAlmostPoint(chest, WiggleParams()), 900, 400)
//withdraw the desired inventory preset //withdraw the desired inventory preset
keypress(invKey) controller.keyPress(invKey)
sleepForNTicks(1) controller.sleepForNTicks(1)
//press the hotkey that causes action without dialogue //press the hotkey that causes action without dialogue
keypress(hotKey) controller.keyPress(hotKey)
sleepForNTicks(1) controller.sleepForNTicks(1)
} }
/** /**
@ -317,24 +318,24 @@ class Agent: Doer() {
waitDurationVarianceMillis: Long waitDurationVarianceMillis: Long
) { ) {
//move to the bank and open the interface //move to the bank and open the interface
moveMouseLeftClickAndSleep( controller.moveMouseLeftClickAndSleep(
getAlmostPoint(chest, Doer.WiggleParams()), controller.getAlmostPoint(chest, WiggleParams()),
travelDurationMillis, travelDurationMillis,
travelDurationVarianceMillis travelDurationVarianceMillis
) )
//withdraw desired loadout //withdraw desired loadout
keypress(bankPresetHotkey) controller.keyPress(bankPresetHotkey)
sleepForNTicks(1) controller.sleepForNTicks(1)
//move to station and open the crafting dialog //move to station and open the crafting dialog
moveMouseLeftClickAndSleep(station, travelDurationMillis, travelDurationVarianceMillis) controller.moveMouseLeftClickAndSleep(station, travelDurationMillis, travelDurationVarianceMillis)
//start the crafting task //start the crafting task
keypress(KeyEvent.VK_SPACE) controller.keyPress(KeyEvent.VK_SPACE)
//wait for it to complete //wait for it to complete
sleep(waitDurationMillis, waitDurationVarianceMillis) controller.sleep(waitDurationMillis, waitDurationVarianceMillis)
} }
/*============================================================================================================== /*==============================================================================================================

View File

@ -32,7 +32,30 @@ import kotlin.random.Random
* *
* @constructor Creates a Doer instance with a Robot. * @constructor Creates a Doer instance with a Robot.
*/ */
open class Doer(private val robot: Robot = Robot()) {
interface InputController {
fun moveMouse(point: Point)
fun mouseClick(button: Int)
fun keyPress(keyCode: Int)
fun sleep(duration: Long)
fun scrollIn(sleepDur: Long, sleepDurVariance: Long)
fun scrollOut(sleepDur: Long, sleepDurVariance: Long)
}
interface DesktopController{
fun getPointerLocation(): Point
}
data class WiggleParams(val xWiggle: Int = 25, val yWiggle: Int = 25)
open class RobotController(private val robot: Robot = Robot()): InputController, DesktopController {
companion object { companion object {
/** /**
* The duration in milliseconds of one "tick". The duration of 600ms matches the tick duration of game servers. * The duration in milliseconds of one "tick". The duration of 600ms matches the tick duration of game servers.
@ -60,38 +83,6 @@ open class Doer(private val robot: Robot = Robot()) {
*/ */
private val LATENCY_PADDING_MS = 500L private val LATENCY_PADDING_MS = 500L
/**
* Data class to hold parameters for random wiggle amounts when moving the mouse. This is useful for avoiding
* "robotic" location patterns on the screen. You'll still converge into an absolutely perfect box, but meh.
*
* This holds the maximum x and y wiggle offset values to use when randomly
* offsetting mouse movements to make them less robotic.
*
* This class is used to encapsulate the parameters for defining the bounds of allowable click area when calling
* [getAlmostPoint]. The calculation may change over time, so the class is used to decouble the data from the logic.
*
* Usage Example:
* ```
* func main(){
* val doer = Doer()
*
* //we'll create a 100x100 box to click inside of
* val wiggleParams = WiggleParams(100, 100)
*
* //define the center
* val centerPoint = Point(100, 200)
*
* //get a random point from the allowable area
* val randomPoint = doer.getAlmostPoint(centerPoint, wiggleParams)
*
* println("centerPoint: {${centerPoint.x}, ${centerPoint.y}} vs {${randomPoint.x}, ${randomPoint.y}}")
* }
* ```
*
* @param xWiggle The max x offset for both parities. So a xWiggle value of 5 will result in a value of x +/- 5, default 25.
* @param yWiggle The max y offset for both parities. So a yWiggle value of 5 will result in a value of y +/- 5, default 25.
*/
data class WiggleParams(val xWiggle: Int = 25, val yWiggle: Int = 25)
/** /**
* Moves the mouse cursor to the given [Point]. * Moves the mouse cursor to the given [Point].
@ -111,10 +102,10 @@ open class Doer(private val robot: Robot = Robot()) {
*``` *```
* *
* *
* @param p The [Point] representing the x and y coordinates to move the mouse to. * @param point The [Point] representing the x and y coordinates to move the mouse to.
*/ */
fun mouseMove(p: Point) { override fun moveMouse(point: Point) {
robot.mouseMove(p.x, p.y) robot.mouseMove(point.x, point.y)
} }
/** /**
@ -129,7 +120,7 @@ open class Doer(private val robot: Robot = Robot()) {
* *
* Returns immediately If button is negative. Button must be a positive integer. * Returns immediately If button is negative. Button must be a positive integer.
*/ */
fun click(button: Int) { override fun mouseClick(button: Int) {
//guardian logic //guardian logic
if (button < 0) { if (button < 0) {
return return
@ -154,7 +145,7 @@ open class Doer(private val robot: Robot = Robot()) {
* *
* returns immediately if key < 0. This can be useful for skipping actions with a -1 * returns immediately if key < 0. This can be useful for skipping actions with a -1
*/ */
fun keypress(key: Int) { override fun keyPress(key: Int) {
//guardian logic //guardian logic
if (key < 0) { if (key < 0) {
return return
@ -180,10 +171,10 @@ open class Doer(private val robot: Robot = Robot()) {
* @param durRange The random variance to add to the sleep duration. * @param durRange The random variance to add to the sleep duration.
*/ */
fun moveMouseLeftClickAndSleep(p: Point, dur: Long, durRange: Long) { fun moveMouseLeftClickAndSleep(p: Point, dur: Long, durRange: Long) {
mouseMove(p) moveMouse(p)
sleep(100, 50) sleep(100, 50)
//left click //left click
click(InputEvent.BUTTON1_DOWN_MASK) mouseClick(InputEvent.BUTTON1_DOWN_MASK)
sleep(dur, durRange) sleep(dur, durRange)
} }
@ -265,7 +256,7 @@ open class Doer(private val robot: Robot = Robot()) {
* *
* @param dur The sleep duration in milliseconds. * @param dur The sleep duration in milliseconds.
*/ */
fun sleep(dur: Long) { override fun sleep(dur: Long) {
TimeUnit.MILLISECONDS.sleep(dur) TimeUnit.MILLISECONDS.sleep(dur)
} }
@ -297,7 +288,7 @@ open class Doer(private val robot: Robot = Robot()) {
* Uses the Robot [mouseWheel] method to scroll up and then sleeps * Uses the Robot [mouseWheel] method to scroll up and then sleeps
* for a random duration between 16-32ms to pace the scrolling. * for a random duration between 16-32ms to pace the scrolling.
*/ */
fun scrollOut(sleepDur: Long, sleepDurVariance: Long) { override fun scrollOut(sleepDur: Long, sleepDurVariance: Long) {
robot.mouseWheel(1) robot.mouseWheel(1)
sleep(sleepDur, sleepDurVariance) sleep(sleepDur, sleepDurVariance)
} }
@ -308,7 +299,7 @@ open class Doer(private val robot: Robot = Robot()) {
* Uses the Robot [mouseWheel] method to scroll up and then sleeps * Uses the Robot [mouseWheel] method to scroll up and then sleeps
* for a random duration between 16-32ms to pace the scrolling. * for a random duration between 16-32ms to pace the scrolling.
*/ */
fun scrollIn(sleepDur: Long, sleepDurVariance: Long) { override fun scrollIn(sleepDur: Long, sleepDurVariance: Long) {
robot.mouseWheel(-1) robot.mouseWheel(-1)
sleep(sleepDur, sleepDurVariance) sleep(sleepDur, sleepDurVariance)
} }
@ -321,7 +312,7 @@ open class Doer(private val robot: Robot = Robot()) {
* *
* @return The [Point] representing the mouse pointer's x and y coordinates. * @return The [Point] representing the mouse pointer's x and y coordinates.
*/ */
fun getPointerLocation(): Point { override fun getPointerLocation(): Point {
return MouseInfo.getPointerInfo().location return MouseInfo.getPointerInfo().location
} }
@ -388,7 +379,7 @@ open class Doer(private val robot: Robot = Robot()) {
val points = arrayListOf(top, bottomleft, topright, topleft, bottomright) val points = arrayListOf(top, bottomleft, topright, topleft, bottomright)
for (i in 0 until 10) { for (i in 0 until 10) {
for (point in points) { for (point in points) {
mouseMove(point) moveMouse(point)
sleep(32) sleep(32)
} }
} }

View File

@ -125,7 +125,7 @@ object Routines {
KeyEvent.VK_F2, KeyEvent.VK_F2,
KeyEvent.VK_2, KeyEvent.VK_2,
26000, 26000,
Doer.TICK_DURATION_MS, RobotController.TICK_DURATION_MS,
) )
Agent.doStandingTask(params) Agent.doStandingTask(params)
} }
@ -152,7 +152,7 @@ object Routines {
KeyEvent.VK_F3, KeyEvent.VK_F3,
KeyEvent.VK_3, KeyEvent.VK_3,
17000, 17000,
Doer.TICK_DURATION_MS, RobotController.TICK_DURATION_MS,
) )
Agent.doStandingTask(params) Agent.doStandingTask(params)
} }
@ -178,7 +178,7 @@ object Routines {
KeyEvent.VK_F4, KeyEvent.VK_F4,
KeyEvent.VK_4, KeyEvent.VK_4,
48600, 48600,
Doer.TICK_DURATION_MS, RobotController.TICK_DURATION_MS,
) )
Agent.doStandingTask(params) Agent.doStandingTask(params)
} }
@ -193,7 +193,7 @@ object Routines {
KeyEvent.VK_F6, KeyEvent.VK_F6,
KeyEvent.VK_MINUS, KeyEvent.VK_MINUS,
19200, 19200,
Doer.TICK_DURATION_MS, RobotController.TICK_DURATION_MS,
) )
Agent.doStandingTask(params) Agent.doStandingTask(params)
} }
@ -215,9 +215,9 @@ object Routines {
KeyEvent.VK_F6, KeyEvent.VK_F6,
-1, //since the travel point is also the dialogue creator, we can omit the hotkey -1, //since the travel point is also the dialogue creator, we can omit the hotkey
19200, 19200,
Doer.TICK_DURATION_MS, RobotController.TICK_DURATION_MS,
travelDurationInMillis, travelDurationInMillis,
Doer.TICK_DURATION_MS RobotController.TICK_DURATION_MS
) )
Agent.doTravelTask(params) Agent.doTravelTask(params)
} }
@ -270,9 +270,9 @@ object Routines {
KeyEvent.VK_F6, KeyEvent.VK_F6,
-1, //since the travel point is also the dialogue creator, we can omit the hotkey -1, //since the travel point is also the dialogue creator, we can omit the hotkey
51000, 51000,
Doer.TICK_DURATION_MS, RobotController.TICK_DURATION_MS,
2000, 2000,
Doer.TICK_DURATION_MS RobotController.TICK_DURATION_MS
) )
println("Resetting the camera. We need to define the reset to compass button...") println("Resetting the camera. We need to define the reset to compass button...")
agent.scrollOutToHeight(8) agent.scrollOutToHeight(8)