From 8d5a8ec3866b90e5e0d91a52a38958104846d407 Mon Sep 17 00:00:00 2001 From: dtookey Date: Sun, 6 Aug 2023 17:43:54 -0400 Subject: [PATCH] attempting to extract agent into interfaces --- src/main/kotlin/Agent.kt | 51 ++++++------ .../kotlin/{Doer.kt => RobotController.kt} | 81 +++++++++---------- src/main/kotlin/Routines.kt | 16 ++-- 3 files changed, 70 insertions(+), 78 deletions(-) rename src/main/kotlin/{Doer.kt => RobotController.kt} (85%) diff --git a/src/main/kotlin/Agent.kt b/src/main/kotlin/Agent.kt index 7addf57..77e2faf 100644 --- a/src/main/kotlin/Agent.kt +++ b/src/main/kotlin/Agent.kt @@ -1,4 +1,5 @@ import java.awt.Point +import java.awt.Robot 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 * activities needed to craft, cook, etc. */ -class Agent: Doer() { +class Agent(val controller: RobotController = RobotController()) { companion object { /** @@ -182,14 +183,14 @@ class Agent: Doer() { */ fun promptUserForPoint(prompt: String): Point { println(prompt) - countDown(5) { + controller.countDown(5) { print("\rtaking point snapshot in $it... ") if (it == 0) { println("\r ") } } - return getPointerLocation() + return controller.getPointerLocation() } /** @@ -209,14 +210,14 @@ class Agent: Doer() { * a reasonable scroll animation speed. */ fun scrollOutToHeight(height: Int, scrollWaitAndVariance: Long = 10L) { - sleep(1000) + controller.sleep(1000) for (i in 0 until height * 2) { - scrollIn(scrollWaitAndVariance, scrollWaitAndVariance) + controller.scrollIn(scrollWaitAndVariance, scrollWaitAndVariance) } for (i in 0 until height) { - scrollOut(scrollWaitAndVariance, scrollWaitAndVariance) + controller.scrollOut(scrollWaitAndVariance, scrollWaitAndVariance) } } @@ -245,19 +246,19 @@ class Agent: Doer() { waitDurationVariance: Long ) { //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 - keypress(bankPresetHotkey) + controller.keyPress(bankPresetHotkey) //sleep for a server tick - sleepForNTicks(1) + controller.sleepForNTicks(1) //open the crafting dialog with the correct hotkey - keypress(craftingDialogueHotkey) + controller.keyPress(craftingDialogueHotkey) //sleep for a server tick - sleepForNTicks(1) + controller.sleepForNTicks(1) //press the "accept" default hotkey - keypress(KeyEvent.VK_SPACE) + controller.keyPress(KeyEvent.VK_SPACE) //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) { //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 - keypress(invKey) + controller.keyPress(invKey) - sleepForNTicks(1) + controller.sleepForNTicks(1) //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 ) { //move to the bank and open the interface - moveMouseLeftClickAndSleep( - getAlmostPoint(chest, Doer.WiggleParams()), + controller.moveMouseLeftClickAndSleep( + controller.getAlmostPoint(chest, WiggleParams()), travelDurationMillis, travelDurationVarianceMillis ) //withdraw desired loadout - keypress(bankPresetHotkey) - sleepForNTicks(1) + controller.keyPress(bankPresetHotkey) + controller.sleepForNTicks(1) //move to station and open the crafting dialog - moveMouseLeftClickAndSleep(station, travelDurationMillis, travelDurationVarianceMillis) + controller.moveMouseLeftClickAndSleep(station, travelDurationMillis, travelDurationVarianceMillis) //start the crafting task - keypress(KeyEvent.VK_SPACE) + controller.keyPress(KeyEvent.VK_SPACE) //wait for it to complete - sleep(waitDurationMillis, waitDurationVarianceMillis) + controller.sleep(waitDurationMillis, waitDurationVarianceMillis) } /*============================================================================================================== diff --git a/src/main/kotlin/Doer.kt b/src/main/kotlin/RobotController.kt similarity index 85% rename from src/main/kotlin/Doer.kt rename to src/main/kotlin/RobotController.kt index 66c5cb5..c3a3caf 100644 --- a/src/main/kotlin/Doer.kt +++ b/src/main/kotlin/RobotController.kt @@ -32,7 +32,30 @@ import kotlin.random.Random * * @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 { /** * 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 - /** - * 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]. @@ -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) { - robot.mouseMove(p.x, p.y) + override fun moveMouse(point: Point) { + 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. */ - fun click(button: Int) { + override fun mouseClick(button: Int) { //guardian logic if (button < 0) { 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 */ - fun keypress(key: Int) { + override fun keyPress(key: Int) { //guardian logic if (key < 0) { return @@ -180,10 +171,10 @@ open class Doer(private val robot: Robot = Robot()) { * @param durRange The random variance to add to the sleep duration. */ fun moveMouseLeftClickAndSleep(p: Point, dur: Long, durRange: Long) { - mouseMove(p) + moveMouse(p) sleep(100, 50) //left click - click(InputEvent.BUTTON1_DOWN_MASK) + mouseClick(InputEvent.BUTTON1_DOWN_MASK) sleep(dur, durRange) } @@ -265,7 +256,7 @@ open class Doer(private val robot: Robot = Robot()) { * * @param dur The sleep duration in milliseconds. */ - fun sleep(dur: Long) { + override fun sleep(dur: Long) { 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 * 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) 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 * 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) 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. */ - fun getPointerLocation(): Point { + override fun getPointerLocation(): Point { return MouseInfo.getPointerInfo().location } @@ -388,7 +379,7 @@ open class Doer(private val robot: Robot = Robot()) { val points = arrayListOf(top, bottomleft, topright, topleft, bottomright) for (i in 0 until 10) { for (point in points) { - mouseMove(point) + moveMouse(point) sleep(32) } } diff --git a/src/main/kotlin/Routines.kt b/src/main/kotlin/Routines.kt index 219d77e..31f16ef 100644 --- a/src/main/kotlin/Routines.kt +++ b/src/main/kotlin/Routines.kt @@ -125,7 +125,7 @@ object Routines { KeyEvent.VK_F2, KeyEvent.VK_2, 26000, - Doer.TICK_DURATION_MS, + RobotController.TICK_DURATION_MS, ) Agent.doStandingTask(params) } @@ -152,7 +152,7 @@ object Routines { KeyEvent.VK_F3, KeyEvent.VK_3, 17000, - Doer.TICK_DURATION_MS, + RobotController.TICK_DURATION_MS, ) Agent.doStandingTask(params) } @@ -178,7 +178,7 @@ object Routines { KeyEvent.VK_F4, KeyEvent.VK_4, 48600, - Doer.TICK_DURATION_MS, + RobotController.TICK_DURATION_MS, ) Agent.doStandingTask(params) } @@ -193,7 +193,7 @@ object Routines { KeyEvent.VK_F6, KeyEvent.VK_MINUS, 19200, - Doer.TICK_DURATION_MS, + RobotController.TICK_DURATION_MS, ) Agent.doStandingTask(params) } @@ -215,9 +215,9 @@ object Routines { KeyEvent.VK_F6, -1, //since the travel point is also the dialogue creator, we can omit the hotkey 19200, - Doer.TICK_DURATION_MS, + RobotController.TICK_DURATION_MS, travelDurationInMillis, - Doer.TICK_DURATION_MS + RobotController.TICK_DURATION_MS ) Agent.doTravelTask(params) } @@ -270,9 +270,9 @@ object Routines { KeyEvent.VK_F6, -1, //since the travel point is also the dialogue creator, we can omit the hotkey 51000, - Doer.TICK_DURATION_MS, + RobotController.TICK_DURATION_MS, 2000, - Doer.TICK_DURATION_MS + RobotController.TICK_DURATION_MS ) println("Resetting the camera. We need to define the reset to compass button...") agent.scrollOutToHeight(8)