Seriously. Weekend.
This commit is contained in:
parent
d0dcdffb9c
commit
c36583631c
@ -1,6 +1,7 @@
|
|||||||
package controllers
|
package controllers
|
||||||
|
|
||||||
import java.awt.Point
|
import java.awt.Point
|
||||||
|
import kotlin.random.Random
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -55,4 +56,71 @@ interface InputController {
|
|||||||
* Same as [scrollIn] but moves the scroll wheel backward.
|
* Same as [scrollIn] but moves the scroll wheel backward.
|
||||||
*/
|
*/
|
||||||
fun scrollOut(sleepDurationMillis: Long, sleepDurationVarianceMillis: Long)
|
fun scrollOut(sleepDurationMillis: Long, sleepDurationVarianceMillis: Long)
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a random point near the given [point] within specified bounds.
|
||||||
|
*
|
||||||
|
* The returned point will have a random offset from [point] in both x and y directions. The maximum offset in each
|
||||||
|
* direction is controlled by [params].
|
||||||
|
*
|
||||||
|
* @param point The reference point to offset from
|
||||||
|
* @param params The max x and y variance
|
||||||
|
* @return A new random [Point] near [point]
|
||||||
|
*/
|
||||||
|
fun getNearbyPoint(point: Point, params: PointerVarianceBounds = PointerVarianceBounds()): Point {
|
||||||
|
// Generate random x and y offsets within the given variance bounds
|
||||||
|
val xDelta = Random.nextInt(0, params.xVariance)
|
||||||
|
val yDelta = Random.nextInt(0, params.yVariance)
|
||||||
|
|
||||||
|
// Determine x and y direction (-1 or 1) by a random Boolean
|
||||||
|
val xDirection = if (Random.nextBoolean()) 1 else -1
|
||||||
|
val yDirection = if (Random.nextBoolean()) 1 else -1
|
||||||
|
|
||||||
|
// Apply the offsets in their random directions to the x and y values of the reference point
|
||||||
|
return Point(
|
||||||
|
point.x + (xDelta * xDirection),
|
||||||
|
point.y + (yDelta * yDirection)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Animates mouse movement from a start point to an end point over a duration.
|
||||||
|
*
|
||||||
|
* The movement will follow an approximation of a sigmoid velocity curve, accelerating
|
||||||
|
* at the start and decelerating at the end.
|
||||||
|
*
|
||||||
|
* The path between start and end points will be varied randomly within the given
|
||||||
|
* variance bounds each tick to simulate human imperfection.
|
||||||
|
*
|
||||||
|
* @param startPoint The starting mouse location
|
||||||
|
* @param endPoint The ending mouse location
|
||||||
|
* @param travelDurationMillis Total time in milliseconds for the movement
|
||||||
|
* @param varianceBounds The max x and y variance each tick
|
||||||
|
*/
|
||||||
|
@Deprecated("Not finished. This will panic. You were warned.",
|
||||||
|
ReplaceWith("TODO(\"Implement this once we figure out how to approximate sigmoid movement and timing\")")
|
||||||
|
)
|
||||||
|
fun animateMoveMouse(
|
||||||
|
startPoint: Point,
|
||||||
|
endPoint: Point,
|
||||||
|
travelDurationMillis: Long,
|
||||||
|
varianceBounds: PointerVarianceBounds = PointerVarianceBounds()
|
||||||
|
) {
|
||||||
|
//we're going to leave this as something to do, but this will remove the need to implement it everywhere
|
||||||
|
TODO("Implement this once we figure out how to approximate sigmoid movement and timing")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds x and y variance bounds for random point generation.
|
||||||
|
*
|
||||||
|
* Used as parameter in [MousePointerObserver.getNearbyPoint] to control the allowed offset range.
|
||||||
|
*
|
||||||
|
* @see MousePointerObserver.getNearbyPoint()
|
||||||
|
*/
|
||||||
|
data class PointerVarianceBounds(
|
||||||
|
val xVariance: Int = 25,
|
||||||
|
val yVariance: Int = 25
|
||||||
|
)
|
||||||
|
|||||||
@ -18,97 +18,13 @@ interface MousePointerObserver {
|
|||||||
/**
|
/**
|
||||||
* Gets the current pointer/mouse location on the desktop.
|
* Gets the current pointer/mouse location on the desktop.
|
||||||
*
|
*
|
||||||
* This returns a [Point] representing the x, y coordinates of the mouse pointer on the screen.
|
* @return The current [Point] representing the x, y coordinates of the mouse pointer on the screen.
|
||||||
*
|
|
||||||
* For example:
|
|
||||||
*
|
|
||||||
* ```
|
|
||||||
* val mouseLocation = getPointerLocation()
|
|
||||||
*
|
|
||||||
* println(mouseLocation) // Might print "Point[x=1920,y=1080]"
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* @return The current [Point] location of the mouse pointer on the screen.
|
|
||||||
*/
|
*/
|
||||||
fun getPointerLocation(): Point {
|
fun getPointerLocation(): Point {
|
||||||
return MouseInfo.getPointerInfo().location
|
return MouseInfo.getPointerInfo().location
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a point near the given [point], with some random wiggle.
|
|
||||||
*
|
|
||||||
* This generates a new point that is randomly offset from the given [point]
|
|
||||||
* by an amount controlled by the given [MouseWiggleParams].
|
|
||||||
*
|
|
||||||
* Usage example:
|
|
||||||
*
|
|
||||||
* ```
|
|
||||||
* val base = Point(10, 20)
|
|
||||||
* val params = WiggleParams(xWiggle = 5, yWiggle = 5)
|
|
||||||
* val randomPoint = getAlmostPoint(base, params)
|
|
||||||
*
|
|
||||||
* // randomPoint might be (8, 22)
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* Alternatively, params may be omitted to use the default WiggleParams values
|
|
||||||
* ```
|
|
||||||
* val base = Point(10, 20)
|
|
||||||
* val randomPoint = getAlmostPoint(base)
|
|
||||||
*
|
|
||||||
* // randomPoint might be (8, 22)
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* @param point The base point to start from
|
|
||||||
* @param params The wiggle parameters that control the random offset amount
|
|
||||||
* @return A new [Point] near the given point with some random wiggle applied
|
|
||||||
*/
|
|
||||||
fun getAlmostPoint(point: Point, params: MouseWiggleParams = MouseWiggleParams()): Point {
|
|
||||||
val xDel = Random.nextInt(0, params.xWiggle)
|
|
||||||
val yDel = Random.nextInt(0, params.yWiggle)
|
|
||||||
|
|
||||||
//flip two coins, determine direction based on the parity of the results
|
|
||||||
val xDir = if (Random.nextDouble() > 0.5) {
|
|
||||||
1
|
|
||||||
} else {
|
|
||||||
-1
|
|
||||||
}
|
|
||||||
val yDir = if (Random.nextDouble() > 0.5) {
|
|
||||||
1
|
|
||||||
} else {
|
|
||||||
-1
|
|
||||||
}
|
|
||||||
|
|
||||||
return Point(point.x + (xDel * xDir), point.y + (yDel * yDir))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Data class to hold wiggle parameters for mouse movement.
|
|
||||||
*
|
|
||||||
* This simple data class holds two integer properties for x and y wiggle amounts.
|
|
||||||
* These are used when generating simulated mouse movements to add some variance
|
|
||||||
* and randomness to the coordinates.
|
|
||||||
*
|
|
||||||
* For example, if a target destination point is (100, 200), the wiggle params
|
|
||||||
* might generate an actual movement point like (102, 198) to add some randomness.
|
|
||||||
*
|
|
||||||
* Usage:
|
|
||||||
*
|
|
||||||
* ```
|
|
||||||
* val controller = DesktopController()
|
|
||||||
* val wiggle = WiggleParams(xWiggle = 10, yWiggle = 15)
|
|
||||||
*
|
|
||||||
* val target = Point(100, 200)
|
|
||||||
* val actual = controller.getAlmostPoint(target, wiggle) // (104, 197)
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* @param xWiggle The max amount of variance in x direction. Default 25.
|
|
||||||
* @param yWiggle The max amount of variance in y direction. Default 25.
|
|
||||||
*/
|
|
||||||
data class MouseWiggleParams(
|
|
||||||
val xWiggle: Int = 25,
|
|
||||||
val yWiggle: Int = 25
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|||||||
@ -105,7 +105,7 @@ open class RobotAutomaton(internal val robot: Robot = Robot()) : Automaton {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scrolls the mouse wheel down by one unit.
|
* Scrolls the mouse wheel up by one unit.
|
||||||
*
|
*
|
||||||
* Uses the [Robot.mouseWheel] method to scroll down and then sleeps for a random duration between the given
|
* Uses the [Robot.mouseWheel] method to scroll down and then sleeps for a random duration between the given
|
||||||
* sleepDurationMillis + rand(0, sleepDurationVarianceMillis) ms. This adds variance in scrolling speed.
|
* sleepDurationMillis + rand(0, sleepDurationVarianceMillis) ms. This adds variance in scrolling speed.
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
package game_logic.runescape
|
package game_logic.runescape
|
||||||
|
|
||||||
import controllers.Automaton
|
import controllers.Automaton
|
||||||
import controllers.MouseWiggleParams
|
import controllers.PointerVarianceBounds
|
||||||
import controllers.RobotAutomaton
|
import controllers.RobotAutomaton
|
||||||
import params.StandingTaskParams
|
import params.StandingTaskParams
|
||||||
import params.TravelTaskParams
|
import params.TravelTaskParams
|
||||||
@ -86,7 +86,7 @@ class RSAgent(override val automaton: Automaton = RobotAutomaton()) : RSOrchestr
|
|||||||
taskParams: StandingTaskParams
|
taskParams: StandingTaskParams
|
||||||
) {
|
) {
|
||||||
//open the bank located by the chest parameter
|
//open the bank located by the chest parameter
|
||||||
moveMouseLeftClickAndSleep(automaton.getAlmostPoint(taskParams.bankPoint, MouseWiggleParams(10, 10)), 900, 400)
|
moveMouseLeftClickAndSleep(automaton.getNearbyPoint(taskParams.bankPoint, PointerVarianceBounds(10, 10)), 900, 400)
|
||||||
//withdraw the desired inventory preset
|
//withdraw the desired inventory preset
|
||||||
automaton.keyPress(taskParams.bankPresetHotkey)
|
automaton.keyPress(taskParams.bankPresetHotkey)
|
||||||
//sleep for a server tick
|
//sleep for a server tick
|
||||||
@ -131,7 +131,7 @@ class RSAgent(override val automaton: Automaton = RobotAutomaton()) : RSOrchestr
|
|||||||
) {
|
) {
|
||||||
//move to the bank and open the interface
|
//move to the bank and open the interface
|
||||||
moveMouseLeftClickAndSleep(
|
moveMouseLeftClickAndSleep(
|
||||||
automaton.getAlmostPoint(taskParams.bankPoint, MouseWiggleParams(10, 10)),
|
automaton.getNearbyPoint(taskParams.bankPoint, PointerVarianceBounds(10, 10)),
|
||||||
taskParams.travelDurationMillis,
|
taskParams.travelDurationMillis,
|
||||||
taskParams.travelDurationVarianceMillis
|
taskParams.travelDurationVarianceMillis
|
||||||
)
|
)
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import org.mockito.Mockito.`when`
|
|||||||
import java.awt.Point
|
import java.awt.Point
|
||||||
import java.awt.event.InputEvent
|
import java.awt.event.InputEvent
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
|
||||||
class AutomatonTest {
|
class AutomatonTest {
|
||||||
@ -20,26 +20,21 @@ class AutomatonTest {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
fun `Automaton extends DesktopController`() {
|
fun `Automaton extends DesktopController`() {
|
||||||
|
val automaton = mock(MousePointerObserver::class.java)
|
||||||
val automaton = mock(Automaton::class.java)
|
|
||||||
|
|
||||||
|
|
||||||
// Given
|
// Given
|
||||||
val basePoint = Point(10, 10)
|
val basePoint = Point(10, 10)
|
||||||
val wiggleParams = MouseWiggleParams(xWiggle = 5, yWiggle = 5)
|
|
||||||
|
|
||||||
|
|
||||||
// When
|
// When
|
||||||
`when`(automaton.getAlmostPoint(basePoint, wiggleParams)).thenReturn(Point(12, 8))
|
`when`(automaton.getPointerLocation()).thenReturn(Point(10, 10))
|
||||||
|
|
||||||
val result = automaton.getAlmostPoint(basePoint, wiggleParams)
|
val result = automaton.getPointerLocation()
|
||||||
|
|
||||||
// Then
|
// Then
|
||||||
assertTrue(result.x >= basePoint.x - wiggleParams.xWiggle)
|
assertEquals(basePoint.x, result.x)
|
||||||
assertTrue(result.x <= basePoint.x + wiggleParams.xWiggle)
|
assertEquals(basePoint.y, result.y)
|
||||||
|
|
||||||
assertTrue(result.y >= basePoint.y - wiggleParams.yWiggle)
|
|
||||||
assertTrue(result.y <= basePoint.y + wiggleParams.yWiggle)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -1,62 +0,0 @@
|
|||||||
package controllers
|
|
||||||
|
|
||||||
import kotlin.test.*
|
|
||||||
import org.mockito.Mockito.*
|
|
||||||
import java.awt.Point
|
|
||||||
|
|
||||||
|
|
||||||
class DesktopControllerTest {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that getPointerLocation() returns the mocked mouse position.
|
|
||||||
*
|
|
||||||
* Creates a mock DesktopController instance.
|
|
||||||
* Mocks the getPointerLocation() method to return a fixed point.
|
|
||||||
* Calls getPointerLocation() on the mock controller.
|
|
||||||
* Retrieves the returned point.
|
|
||||||
* Asserts the x and y values match the mocked values.
|
|
||||||
* This validates getPointerLocation() returns the expected mouse position.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
fun `getPointerLocation returns mouse position`() {
|
|
||||||
val controller = mock(MousePointerObserver::class.java)
|
|
||||||
|
|
||||||
// Mock mouse position
|
|
||||||
`when`(controller.getPointerLocation()).thenReturn(Point(100, 200))
|
|
||||||
|
|
||||||
// Assert mouse position is returned
|
|
||||||
val pos = controller.getPointerLocation()
|
|
||||||
assertEquals(100, pos.x)
|
|
||||||
assertEquals(200, pos.y)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that getAlmostPoint() returns a wiggly point different than the source.
|
|
||||||
*
|
|
||||||
* Creates a mock DesktopController instance.
|
|
||||||
* Creates a WiggleParams with x and y wiggle amounts.
|
|
||||||
* Mocks getAlmostPoint() to return a fixed offset point based on the params.
|
|
||||||
* Calls getAlmostPoint() with a source point and the wiggle params.
|
|
||||||
* Retrieves the returned wiggly point.
|
|
||||||
* Asserts the x and y values match the expected wiggly values.
|
|
||||||
* Also asserts the x and y values are different than the source point.
|
|
||||||
* This validates getAlmostPoint() returns a randomly offset point.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
fun `getAlmostPoint returns wiggly point`() {
|
|
||||||
val controller = mock(MousePointerObserver::class.java)
|
|
||||||
val params = MouseWiggleParams(xWiggle = 10, yWiggle = 10)
|
|
||||||
|
|
||||||
// Mock random wiggle
|
|
||||||
`when`(controller.getAlmostPoint(Point(100, 200), params))
|
|
||||||
.thenReturn(Point(105, 205))
|
|
||||||
|
|
||||||
// Assert wiggly point
|
|
||||||
val wiggly = controller.getAlmostPoint(Point(100, 200), params)
|
|
||||||
assertEquals(105, wiggly.x)
|
|
||||||
assertEquals(205, wiggly.y)
|
|
||||||
assertNotEquals(100, wiggly.x)
|
|
||||||
assertNotEquals(200, wiggly.y)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue
Block a user