refactored everything into parametric interfaces

This commit is contained in:
dtookey 2023-08-05 07:23:27 -04:00
parent f919179c86
commit 075117e354
5 changed files with 290 additions and 142 deletions

View File

@ -28,6 +28,34 @@ class Agent {
* Constant for the Minus/Dash key code. * Constant for the Minus/Dash key code.
*/ */
const val Minus = KeyEvent.VK_MINUS const val Minus = KeyEvent.VK_MINUS
fun doStandingTask(params: StandingTaskParams) {
val agent = params.agent
agent.doLoop(params.totalVolume, params.volumePerStep) {
agent.bankStandForLoop(
params.bankPoint,
params.bankPresetHotkey,
params.craftingDialogHotkey,
params.craftingWaitDurationMillis,
params.craftingWaitDurationVarianceMillis
)
}
}
fun doTravelTask(params: TravelTaskParams) {
val agent = params.agent
agent.doLoop(params.totalVolume, params.volumePerStep) {
agent.processAtStationNearBank(
params.bankPoint,
params.travelPoint,
params.bankPresetHotkey,
params.travelDurationMillis,
params.travelDurationVarianceMillis,
params.craftingWaitDurationMillis,
params.craftingWaitDurationVarianceMillis
)
}
}
} }
/** /**
@ -193,8 +221,8 @@ class Agent {
* Performs automated banking steps in a loop at the given chest location. * Performs automated banking steps in a loop at the given chest location.
* *
* @param chest The Point location of the bank chest to click on. * @param chest The Point location of the bank chest to click on.
* @param invHotkey The key for the inventory preset to withdraw. * @param bankPresetHotkey The key for the inventory preset to withdraw.
* @param hotbarHotkey The key for the crafting preset to open. * @param craftingDialogueHotkey The key for the crafting preset to open.
* @param waitDurationMillis The time in ms to wait at each loop iteration. * @param waitDurationMillis The time in ms to wait at each loop iteration.
* @param waitDurationVariance Random variance to add to wait time. * @param waitDurationVariance Random variance to add to wait time.
* *
@ -206,21 +234,21 @@ class Agent {
* *
* Useful for automated banking behaviors like crafting or herblore. * Useful for automated banking behaviors like crafting or herblore.
*/ */
fun bankStandForLoop( private fun bankStandForLoop(
chest: Point, chest: Point,
invHotkey: Int, bankPresetHotkey: Int,
hotbarHotkey: Int, craftingDialogueHotkey: Int,
waitDurationMillis: Long, waitDurationMillis: Long,
waitDurationVariance: Long waitDurationVariance: Long
) { ) {
//open the bank located by the chest parameter //open the bank located by the chest parameter
doer.moveMouseLeftClickAndSleep(doer.getAlmostPoint(chest, Doer.WiggleParams()), 900, 400) doer.moveMouseLeftClickAndSleep(doer.getAlmostPoint(chest, Doer.WiggleParams()), 900, 400)
//withdraw the desired inventory preset //withdraw the desired inventory preset
doer.keypress(invHotkey) doer.keypress(bankPresetHotkey)
//sleep for a server tick //sleep for a server tick
doer.sleepForNTicks(1) doer.sleepForNTicks(1)
//open the crafting dialog with the correct hotkey //open the crafting dialog with the correct hotkey
doer.keypress(hotbarHotkey) doer.keypress(craftingDialogueHotkey)
//sleep for a server tick //sleep for a server tick
doer.sleepForNTicks(1) doer.sleepForNTicks(1)
//press the "accept" default hotkey //press the "accept" default hotkey
@ -263,11 +291,11 @@ class Agent {
* *
* @param chest The Point location of the bank chest. * @param chest The Point location of the bank chest.
* @param station The Point location of the processing station. * @param station The Point location of the processing station.
* @param invHotkey The inventory preset hotkey to withdraw at bank. * @param bankPresetHotkey The inventory preset hotkey to withdraw at bank.
* @param travelDurationMillis Base travel time between bank and station. * @param travelDurationMillis Base travel time between bank and station.
* @param travelDurationVariance Random variance to add to travel time. * @param travelDurationVarianceMillis Random variance to add to travel time.
* @param waitDurationMillis Base wait time for processing at station. * @param waitDurationMillis Base wait time for processing at station.
* @param waitDurationVariance Random variance to add to wait time. * @param waitDurationVarianceMillis Random variance to add to wait time.
* *
* This handles the steps to go to the bank, withdraw a preset, go to the station, * This handles the steps to go to the bank, withdraw a preset, go to the station,
* open the processing interface, wait, and then loop. * open the processing interface, wait, and then loop.
@ -279,31 +307,31 @@ class Agent {
fun processAtStationNearBank( fun processAtStationNearBank(
chest: Point, chest: Point,
station: Point, station: Point,
invHotkey: Int, bankPresetHotkey: Int,
travelDurationMillis: Long, travelDurationMillis: Long,
travelDurationVariance: Long, travelDurationVarianceMillis: Long,
waitDurationMillis: Long, waitDurationMillis: Long,
waitDurationVariance: Long waitDurationVarianceMillis: Long
) { ) {
//move to the bank and open the interface //move to the bank and open the interface
doer.moveMouseLeftClickAndSleep( doer.moveMouseLeftClickAndSleep(
doer.getAlmostPoint(chest, Doer.WiggleParams()), doer.getAlmostPoint(chest, Doer.WiggleParams()),
travelDurationMillis, travelDurationMillis,
travelDurationVariance travelDurationVarianceMillis
) )
//withdraw desired loadout //withdraw desired loadout
doer.keypress(invHotkey) doer.keypress(bankPresetHotkey)
doer.sleepForNTicks(1) doer.sleepForNTicks(1)
//move to station and open the crafting dialog //move to station and open the crafting dialog
doer.moveMouseLeftClickAndSleep(station, travelDurationMillis, travelDurationVariance) doer.moveMouseLeftClickAndSleep(station, travelDurationMillis, travelDurationVarianceMillis)
//start the crafting task //start the crafting task
doer.keypress(KeyEvent.VK_SPACE) doer.keypress(KeyEvent.VK_SPACE)
//wait for it to complete //wait for it to complete
doer.sleep(waitDurationMillis, waitDurationVariance) doer.sleep(waitDurationMillis, waitDurationVarianceMillis)
} }
/*============================================================================================================== /*==============================================================================================================

View File

@ -33,7 +33,7 @@ import kotlin.random.Random
* @constructor Creates a Doer instance with a Robot. * @constructor Creates a Doer instance with a Robot.
*/ */
class Doer(private val robot: Robot = Robot()) { class Doer(private val robot: Robot = Robot()) {
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.
* *
@ -44,7 +44,10 @@ class Doer(private val robot: Robot = Robot()) {
* *
* For example, 5 ticks with this value would be 5 * 600 = 3000ms sleep duration. * For example, 5 ticks with this value would be 5 * 600 = 3000ms sleep duration.
*/ */
private val TICK_DURATION_MS = 600L const val TICK_DURATION_MS = 600L
}
/** /**
* Extra padding in milliseconds added before actions to account for latency. 500ms is entirely arbitrary. It is * Extra padding in milliseconds added before actions to account for latency. 500ms is entirely arbitrary. It is
@ -116,18 +119,22 @@ class Doer(private val robot: Robot = Robot()) {
} }
/** /**
* Performs a mouse click with the specified mouse button. * Performs a mouse click of the specified button.
* *
* This uses the Robot [mousePress] and [mouseRelease] methods to click the * This uses the Robot to press and release the given mouse button.
* mouse button specified by [button].
* *
* It sleeps for a small random duration between press and release to add * A random sleep is added in between pressing and releasing the button
* variance to the click timing. * to add variance and avoid robotic timing.
* *
* @param button The mouse button to click, as a button mask from [InputEvent]. * @param button The button to click. Must be a valid constant like [InputEvent.BUTTON1_MASK].
*
* Returns immediately If button is negative. Button must be a positive integer.
*/ */
fun click(button: Int) { private fun click(button: Int) {
//guardian logic
if (button < 0) {
return
}
robot.mousePress(button) robot.mousePress(button)
//we add in some random time variance here to appear less robotic //we add in some random time variance here to appear less robotic
@ -137,17 +144,22 @@ class Doer(private val robot: Robot = Robot()) {
} }
/** /**
* Presses and releases a keyboard key. * Presses and releases the given key.
* *
* This uses the Robot [keyPress] and [keyRelease] methods to press * This uses the Robot to simulate pressing and releasing the key with the given key code.
* and release the key specified by [key].
* *
* It sleeps for a small random duration in between key press and release * A random sleep is added after pressing the key before releasing it to add variance
* to pace the keystrokes. * and avoid robotic timing.
* *
* @param key The key code of the key to press, from [java.awt.event.KeyEvent]. * @param key The key code of the key to press, such as [KeyEvent.VK_A].
*
* returns immediately if key < 0. This can be useful for skipping actions with a -1
*/ */
fun keypress(key: Int) { fun keypress(key: Int) {
//guardian logic
if (key < 0) {
return
}
robot.keyPress(key) robot.keyPress(key)

View File

@ -2,7 +2,7 @@ import java.awt.Point
fun main() { fun main() {
// Routines.fullRunIncense(0, 8916, 9462, 4808) // Routines.fullRunIncense(0, 8916, 9462, 4808)
val params = RoutineParams(1000, 28, chest = Point(0, 0)) val params = TaskParams(1000, 28, chest = Point(0, 0))
Routines.processInventoryAtFurnace(params) Routines.processInventoryAtFurnace(params)
} }

View File

@ -46,32 +46,28 @@ object Routines {
// Loop to clean grimy herbs: // Loop to clean grimy herbs:
// Withdraw herb preset, clean without dialog at bank // Withdraw herb preset, clean without dialog at bank
if (volHerbs > 0) { if (volHerbs > 0) {
val params = RoutineParams(volHerbs, CommonVolumesPerStep.FullInventory, agent, chest) cleanHerbs(volHerbs)
cleanHerbs(params)
} }
println("\rHerbs cleaned") println("\rHerbs cleaned")
// Loop to cut magic logs into sticks: // Loop to cut magic logs into sticks:
// Withdraw log preset, cut logs using hotkey at bank // Withdraw log preset, cut logs using hotkey at bank
if (volLogs > 0) { if (volLogs > 0) {
val params = RoutineParams(volLogs, CommonVolumesPerStep.FullInventory, agent, chest) cutIncenseSticks(volLogs)
cutIncenseSticks(params)
} }
println("\rLogs cut into sticks") println("\rLogs cut into sticks")
// Loop to coat sticks in ashes: // Loop to coat sticks in ashes:
// Withdraw ash preset, coat sticks using hotkey at bank // Withdraw ash preset, coat sticks using hotkey at bank
if (volAshes > 0) { if (volAshes > 0) {
val params = RoutineParams(volAshes, CommonVolumesPerStep.CoatingIncenseWithAsh, agent, chest) coatIncenseSticks(volAshes)
coatIncenseSticks(params)
} }
println("\rSticks coated in ashes") println("\rSticks coated in ashes")
// Loop to infuse clean herbs into sticks: // Loop to infuse clean herbs into sticks:
// Withdraw herb preset, infuse sticks using hotkey at bank // Withdraw herb preset, infuse sticks using hotkey at bank
if (volCleanHerbs > 0) { if (volCleanHerbs > 0) {
val params = RoutineParams(volCleanHerbs, CommonVolumesPerStep.InfusingIncenseWithHerb, agent, chest) infuseIncenseSticks(volCleanHerbs)
infuseIncenseSticks(params)
} }
println("\rClean herbs infused") println("\rClean herbs infused")
@ -81,72 +77,108 @@ object Routines {
} }
@Deprecated("Needs validation before you use it for realsies") @Deprecated("Needs validation before you use it for realsies")
fun cleanHerbs( fun cleanHerbs(volume: Int, agent: Agent = Agent(), bankPoint: Point = agent.getBankPoint()) {
params: RoutineParams val params = StandingTaskParams(
) { volume,
params.agent.doLoop(params.totalVolume, params.volumePerStep) { 28,
params.agent.bankStandWithoutDialog(params.chest, KeyEvent.VK_F1, KeyEvent.VK_1) agent,
} bankPoint,
KeyEvent.VK_F1,
KeyEvent.VK_1,
0,
0
)
Agent.doStandingTask(params)
} }
@Deprecated("Needs validation before you use it for realsies") @Deprecated("Needs validation before you use it for realsies")
fun cutIncenseSticks( fun cutIncenseSticks(volume: Int, agent: Agent = Agent(), bankPoint: Point = agent.getBankPoint()) {
params: RoutineParams val params = StandingTaskParams(
) { volume,
params.agent.doLoop(params.totalVolume, params.volumePerStep) { 28,
params.agent.bankStandForLoop(params.chest, KeyEvent.VK_F2, KeyEvent.VK_2, 26000, 1200) agent,
} bankPoint,
KeyEvent.VK_F2,
KeyEvent.VK_2,
26000,
Doer.TICK_DURATION_MS,
)
Agent.doStandingTask(params)
} }
@Deprecated("Needs validation before you use it for realsies") @Deprecated("Needs validation before you use it for realsies")
fun coatIncenseSticks( fun coatIncenseSticks(volume: Int, agent: Agent = Agent(), bankPoint: Point = agent.getBankPoint()) {
params: RoutineParams val params = StandingTaskParams(
) { volume,
params.agent.doLoop(params.totalVolume, params.volumePerStep) { 28,
params.agent.bankStandForLoop(params.chest, KeyEvent.VK_F3, KeyEvent.VK_3, 21000, 600) agent,
} bankPoint,
KeyEvent.VK_F3,
KeyEvent.VK_3,
21000,
Doer.TICK_DURATION_MS,
)
Agent.doStandingTask(params)
} }
@Deprecated("Needs validation before you use it for realsies") @Deprecated("Needs validation before you use it for realsies")
fun infuseIncenseSticks( fun infuseIncenseSticks(volume: Int, agent: Agent = Agent(), bankPoint: Point = agent.getBankPoint()) {
params: RoutineParams val params = StandingTaskParams(
) { volume,
params.agent.doLoop(params.totalVolume, params.volumePerStep) { 28,
params.agent.bankStandForLoop(params.chest, KeyEvent.VK_F4, KeyEvent.VK_4, 48600, 600) agent,
} bankPoint,
KeyEvent.VK_F4,
KeyEvent.VK_4,
48600,
Doer.TICK_DURATION_MS,
)
Agent.doStandingTask(params)
} }
@Deprecated("Needs validation before you use it for realsies") @Deprecated("Needs validation before you use it for realsies")
fun craftPotionAtBank( fun craftPotionAtBank(volume: Int, agent: Agent = Agent(), bankPoint: Point = agent.getBankPoint()) {
params: RoutineParams val params = StandingTaskParams(
) { volume,
params.agent.doLoop(params.totalVolume, params.volumePerStep) { 28,
params.agent.bankStandForLoop(params.chest, Agent.F6, Agent.Minus, 19200, 600) agent,
} bankPoint,
KeyEvent.VK_F6,
KeyEvent.VK_MINUS,
19200,
Doer.TICK_DURATION_MS,
)
Agent.doStandingTask(params)
} }
@Deprecated("Needs validation before you use it for realsies") @Deprecated("Needs validation before you use it for realsies")
fun potionGrindWithWell( fun potionGrindWithWell(
params: RoutineParams, volume: Int,
travelDurationInMillis: Long travelDurationInMillis: Long,
agent: Agent = Agent(),
bankPoint: Point = agent.getBankPoint()
) { ) {
val agent = Agent()
val chest = agent.getBankPoint()
val well = agent.promptUserForPoint("Put your mouse over the well...") val well = agent.promptUserForPoint("Put your mouse over the well...")
val params = TravelTaskParams(
agent.doLoop(params.totalVolume, params.volumePerStep) { volume,
agent.processAtStationNearBank(chest, well, Agent.F6, travelDurationInMillis, 0, 18600, 600) 28,
} agent,
bankPoint,
well,
KeyEvent.VK_F6,
-1, //since the travel point is also the dialogue creator, we can omit the hotkey
19200,
Doer.TICK_DURATION_MS,
travelDurationInMillis,
Doer.TICK_DURATION_MS
)
Agent.doTravelTask(params)
} }
@Deprecated("Needs validation before you use it for realsies") @Deprecated("Needs validation before you use it for realsies")
fun supremeOverloadGrind( fun supremeOverloadGrind(params: TaskParams) {
params: RoutineParams
) {
val agent = Agent() val agent = Agent()
val chest = agent.getBankPoint() val chest = agent.getBankPoint()
val well = agent.promptUserForPoint("Put your mouse over the well...") val well = agent.promptUserForPoint("Put your mouse over the well...")
@ -157,67 +189,58 @@ object Routines {
} }
fun processInventoryAtFurnace( fun processInventoryAtFurnace(volume: Int) {
params: RoutineParams //these two points are specific to my computer. we need to export these into a file or something
) { val furnaceFromChest = Point(776, 321)
val chestFromFurnance = Point(1713, 843)
val agent = Agent() val agent = Agent()
println("Reset the camera") val params = TravelTaskParams(
volume,
28,
agent,
chestFromFurnance,
furnaceFromChest,
KeyEvent.VK_F6,
-1, //since the travel point is also the dialogue creator, we can omit the hotkey
51000,
Doer.TICK_DURATION_MS,
2000,
Doer.TICK_DURATION_MS
)
println("Resetting the camera. We need to define the reset to compass button...")
agent.scrollOutToHeight(8) agent.scrollOutToHeight(8)
val furnaceFromChest = Point(776, 321) Agent.doTravelTask(params)
val chestFromFurance = Point(1713, 843)
agent.doLoop(params.totalVolume, params.volumePerStep) {
agent.processAtStationNearBank(chestFromFurance, furnaceFromChest, Agent.F6, 2000, 600, 51000, 600)
}
} }
/**
* Processes refined planks into frames at the sawmill near the bank.
*
* This handles the full workflow of:
* - Withdrawing planks preset from bank
* - Walking to the sawmill
* - Using planks on saw to make frames
* - Walking back to bank
* - Depositing frames
*
* The function loops through processing a total volume of planks based on the provided
* RoutineParams.
*
* @param params RoutineParams config including total volume, volume per trip, agent, and chest point.
* @return Nothing.
*/
@Deprecated("Needs validation before you use it for realsies") @Deprecated("Needs validation before you use it for realsies")
fun processRefinedPlanksIntoFrames( fun processRefinedPlanksIntoFrames(params: TaskParams) {
params: RoutineParams
) {
println("You must zoom in all the way and have the compass pointing straight N with a completely top-down view\n you must also be standing at the touch point on the saw") println("You must zoom in all the way and have the compass pointing straight N with a completely top-down view\n you must also be standing at the touch point on the saw")
val agent = Agent() val agent = Agent()
agent.scrollOutToHeight(8) agent.scrollOutToHeight(8)
//the following 2 points are magic numbers from *my* setup and resolution
val sawFromChest = Point(1079, 907) val sawFromChest = Point(1079, 907)
val chestFromSaw = Point(1226, 180) val chestFromSaw = Point(1226, 180)
agent.doLoop(params.totalVolume, params.volumePerStep) {
// //standing at bank with full inv
// d.mouseMove(sawFromChest)
// d.sleep(100, 50)
// //run to saw
// d.click(LeftClick)
// d.sleep(2700, 500)
// //start cutting frames
// d.keypress(Space)
// //waiting
// d.sleep(64000, 1000)
// d.mouseMove(chestFromSaw)
// d.sleep(100, 50)
// //running to bank
// d.click(LeftClick)
// d.sleep(2700, 500)
// d.keypress(F6)
// d.sleep(1200, 500)
// //full inv
agent.doLoop(params.totalVolume, params.volumePerStep) {
agent.processAtStationNearBank(chestFromSaw, sawFromChest, Agent.F6, 2700, 500, 64000, 1000) agent.processAtStationNearBank(chestFromSaw, sawFromChest, Agent.F6, 2700, 500, 64000, 1000)
} }
} }
} }
data class RoutineParams(
val totalVolume: Int,
val volumePerStep: Int,
val agent: Agent = Agent(),
val chest: Point = agent.getBankPoint()
)
object CommonVolumesPerStep {
const val FullInventory = 28
const val TwoReagentFullInventory = 14
const val CoatingIncenseWithAsh = 26
const val InfusingIncenseWithHerb = 27
}

View File

@ -0,0 +1,85 @@
import java.awt.Point
/**
* Configuration parameters for routines.
*
* @param totalVolume The total number of items to process in the routine.
* @param volumePerStep The volume of items to process per loop iteration.
* @param agent The Agent instance to use for actions like banking.
* @param chest The Point location of the bank chest to use.
*/
interface TaskParams {
val totalVolume: Int
val volumePerStep: Int
val agent: Agent
}
interface BankParams{
val bankPoint: Point
val bankPresetHotkey: Int
}
interface CraftingParams{
val craftingDialogHotkey: Int
val craftingWaitDurationMillis: Long
val craftingWaitDurationVarianceMillis: Long
}
interface TravelParams{
val travelPoint: Point
val travelDurationMillis: Long
val travelDurationVarianceMillis: Long
}
data class StandingTaskParams(
override val totalVolume: Int,
override val volumePerStep: Int,
override val agent: Agent,
override val bankPoint: Point,
override val bankPresetHotkey: Int,
override val craftingDialogHotkey: Int,
override val craftingWaitDurationMillis: Long,
override val craftingWaitDurationVarianceMillis: Long
): TaskParams, BankParams, CraftingParams
data class TravelTaskParams(
override val totalVolume: Int,
override val volumePerStep: Int,
override val agent: Agent,
override val bankPoint: Point,
override val travelPoint: Point,
override val bankPresetHotkey: Int,
override val craftingDialogHotkey: Int = -1,
override val craftingWaitDurationMillis: Long,
override val craftingWaitDurationVarianceMillis: Long,
override val travelDurationMillis: Long,
override val travelDurationVarianceMillis: Long
): TaskParams, BankParams, CraftingParams, TravelParams
/**
* CommonVolumesPerStep provides constants for common inventory volumes used during routines.
*/
object CommonVolumesPerStep {
/**
* Full inventory volume constant.
*/
const val FullInventory = 28
/**
* Two-reagent full inventory volume constant.
* For example, when combining two items that fill the inventory.
*/
const val TwoReagentFullInventory = 14
/**
* Volume for coating incense sticks with ashes.
*/
const val CoatingIncenseWithAsh = 26
/**
* Volume for infusing incense sticks with herbs.
*/
const val InfusingIncenseWithHerb = 27
}