Skip to content

Commit

Permalink
Version 5.0.0: massively improved performance by utilizing Project …
Browse files Browse the repository at this point in the history
…Panama rather than JNA for keystate/interception calls, and improved `AimBotThread` sleeping to be more precise
  • Loading branch information
Jire committed Dec 16, 2022
1 parent 2581832 commit a5dcf05
Show file tree
Hide file tree
Showing 14 changed files with 218 additions and 97 deletions.
2 changes: 1 addition & 1 deletion .idea/compiler.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 13 additions & 13 deletions .idea/modules/Overwatcheat.main.iml

Large diffs are not rendered by default.

31 changes: 15 additions & 16 deletions .idea/modules/Overwatcheat.test.iml

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@ The first step is to compile the source code into a usable cheat program.
* Click on the [**Releases**](https://github.com/Jire/Overwatcheat/releases) tab
* Download the latest release ZIP archive
* Extract the contents from the archive to any folder (to your desktop, for example)
* Make sure you have Java Development Kit 8 or later installed
* Make sure you have Java Development Kit 19 or later installed
* Double click on the "_build_" (_build.bat_) script and wait for it to complete

Once those steps are complete, the usable cheat program can be found within the _build_
directory, and will in a directory called **Overwatcheat 3.5.0**.
directory, and will in a directory called **Overwatcheat 5.0.0**.

From within the **Overwatcheat 3.5.0** directory, you can start the cheat by running the _"Start Overwatcheat 3.5.0"_
From within the **Overwatcheat 5.0.0** directory, you can start the cheat by running the _"Start Overwatcheat 5.0.0"_
script.

**Requirements:**
Expand Down
11 changes: 9 additions & 2 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,13 @@ plugins {
}

group = "org.jire.overwatcheat"
version = "4.1.0"
version = "5.0.0"

kotlin {
jvmToolchain {
languageVersion.set(JavaLanguageVersion.of(19))
}
}

dependencies {
implementation(libs.fastutil)
Expand All @@ -34,6 +40,7 @@ dependencies {
application {
applicationName = "Overwatcheat"
mainClass.set("org.jire.overwatcheat.Main")
applicationDefaultJvmArgs += "--enable-native-access=ALL-UNNAMED"
}

tasks {
Expand Down Expand Up @@ -91,6 +98,6 @@ fun File.writeStartBat(name: String, jarName: String) =
"""@echo off
cd /d "%~dp0"
title $name
java -jar "$jarName"
java --enable-native-access=ALL-UNNAMED -jar "$jarName"
pause""".trimIndent()
)
6 changes: 3 additions & 3 deletions src/main/kotlin/org/jire/overwatcheat/Keyboard.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@

package org.jire.overwatcheat

import org.jire.overwatcheat.nativelib.User32
import org.jire.overwatcheat.nativelib.User32Panama

object Keyboard {

fun keyState(virtualKeyCode: Int) = User32.GetKeyState(virtualKeyCode)
fun keyState(virtualKeyCode: Int) = User32Panama.GetKeyState(virtualKeyCode)

fun keyPressed(virtualKeyCode: Int) = keyState(virtualKeyCode) < 0

fun keyReleased(virtualKeyCode: Int) = !keyPressed(virtualKeyCode)

}
}
85 changes: 35 additions & 50 deletions src/main/kotlin/org/jire/overwatcheat/Mouse.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,71 +18,56 @@

package org.jire.overwatcheat

import com.sun.jna.Callback
import org.jire.overwatcheat.nativelib.Kernel32
import org.jire.overwatcheat.nativelib.interception.Interception
import org.jire.overwatcheat.nativelib.interception.InterceptionFilter
import org.jire.overwatcheat.nativelib.interception.InterceptionMouseFlag
import org.jire.overwatcheat.nativelib.interception.InterceptionStroke
import org.jire.overwatcheat.nativelib.interception.InterceptionPanama
import org.jire.overwatcheat.nativelib.interception.InterceptionPanama.interceptionMouseStrokeLayout
import java.lang.Thread.sleep
import java.lang.foreign.MemorySegment
import java.lang.foreign.MemorySession
import java.lang.foreign.ValueLayout

object Mouse : Thread() {
object Mouse {

private val mouseCallback = object : Callback {
fun callback(device: Int) = Interception.interception_is_mouse(device)
}
private val keyboardCallback = object : Callback {
fun callback(device: Int) = Interception.interception_is_keyboard(device)
}
private val context = Interception.interception_create_context()
private val emptyStroke = InterceptionStroke()
private val context = InterceptionPanama.interception_create_context()

override fun run() {
var device: Int
while (Interception.interception_receive(
context,
Interception.interception_wait(context).also { device = it },
emptyStroke,
1
) > 0
) {
if (!emptyStroke.isInjected) {
Interception.interception_send(context, device, emptyStroke, 1)
}
val stroke =
MemorySegment.allocateNative(interceptionMouseStrokeLayout, MemorySession.global()).apply {
set(ValueLayout.JAVA_SHORT, 0, 0) // state
set(ValueLayout.JAVA_SHORT, 2, 0) // flags
set(ValueLayout.JAVA_SHORT, 4, 0) // rolling
set(ValueLayout.JAVA_INT, 8, 0) // x
set(ValueLayout.JAVA_INT, 12, 0) // y
set(
ValueLayout.JAVA_SHORT, 14,
(InterceptionMouseFlag.INTERCEPTION_MOUSE_MOVE_RELATIVE or
InterceptionMouseFlag.INTERCEPTION_MOUSE_CUSTOM).toShort()
) // information
}
Interception.interception_destroy_context(context)
}

val stroke = InterceptionStroke(
0, 0,
(InterceptionMouseFlag.INTERCEPTION_MOUSE_MOVE_RELATIVE or
InterceptionMouseFlag.INTERCEPTION_MOUSE_CUSTOM).toShort(),
0, 0, 0, 0, true
)

fun move(x: Int, y: Int, deviceID: Int) {
stroke.x = x
stroke.y = y
Interception.interception_send(context, deviceID, stroke, 1)
stroke.run {
set(ValueLayout.JAVA_INT, 8, x)
set(ValueLayout.JAVA_INT, 12, y)
}
InterceptionPanama.interception_send(context, deviceID, stroke, 1)
}

fun click(deviceID: Int) {
stroke.x = 0
stroke.y = 0
stroke.code = InterceptionFilter.INTERCEPTION_MOUSE_LEFT_BUTTON_DOWN.toShort()
Interception.interception_send(context, deviceID, stroke, 1)
Thread.sleep(300)
stroke.code = InterceptionFilter.INTERCEPTION_MOUSE_LEFT_BUTTON_UP.toShort()
Interception.interception_send(context, deviceID, stroke, 1)
stroke.run {
setAtIndex(ValueLayout.JAVA_INT, 0, InterceptionFilter.INTERCEPTION_MOUSE_LEFT_BUTTON_DOWN)
set(ValueLayout.JAVA_INT, 8, 0)
set(ValueLayout.JAVA_INT, 12, 0)
}
InterceptionPanama.interception_send(context, deviceID, stroke, 1)
sleep(300)
stroke.setAtIndex(ValueLayout.JAVA_INT, 0, InterceptionFilter.INTERCEPTION_MOUSE_LEFT_BUTTON_UP)
InterceptionPanama.interception_send(context, deviceID, stroke, 1)
}

init {
Kernel32.SetPriorityClass(Kernel32.GetCurrentProcess(), Kernel32.HIGH_PRIORITY_CLASS)
Interception.interception_set_filter(
context,
mouseCallback,
InterceptionFilter.INTERCEPTION_FILTER_MOUSE_MOVE.toShort()
)
start()
}

}
}
13 changes: 7 additions & 6 deletions src/main/kotlin/org/jire/overwatcheat/aimbot/AimBotThread.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import org.jire.overwatcheat.FastRandom
import org.jire.overwatcheat.Keyboard
import org.jire.overwatcheat.Mouse
import org.jire.overwatcheat.settings.Settings
import org.jire.overwatcheat.util.Threads
import java.util.concurrent.ThreadLocalRandom
import kotlin.math.abs
import kotlin.math.max
Expand All @@ -38,8 +39,10 @@ class AimBotThread(
val random = FastRandom()

override fun run() {
priority = MAX_PRIORITY

val tlr = ThreadLocalRandom.current()
while (!interrupted()) {
while (true) {
val elapsed = measureNanoTime {
if (!Keyboard.keyPressed(Settings.aimKey)) {
AimBotState.aimData = 0
Expand All @@ -54,10 +57,8 @@ class AimBotThread(
(Settings.aimDurationMultiplierBase + tlr.nextFloat())
)
val sleepTime = (aimDurationNanos * sleepTimeMultiplier).toLong() - elapsed
if (sleepTime > 0) {
val millis = sleepTime / 1_000_000
val nanos = sleepTime % 1_000_000
sleep(millis, nanos.toInt())
if (sleepTime > 100_000) {
Threads.preciseSleep(sleepTime)
}
}
}
Expand Down Expand Up @@ -117,4 +118,4 @@ class AimBotThread(
}
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ class FrameGrabber(

setOption("offset_x", captureOffsetX.toString())
setOption("offset_y", captureOffsetY.toString())

setOption("draw_mouse", "0")
setOption("show_region", "0")
}

private companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class FrameGrabberThread(
priority = MAX_PRIORITY
frameGrabber.start()
try {
while (!interrupted()) {
while (true) {
val frame = frameGrabber.grabImage()
frameHandler.handle(frame)
}
Expand All @@ -38,4 +38,4 @@ class FrameGrabberThread(
}
}

}
}
34 changes: 34 additions & 0 deletions src/main/kotlin/org/jire/overwatcheat/nativelib/User32Panama.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Free, open-source undetected color cheat for Overwatch!
* Copyright (C) 2017 Thomas G. Nappo
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package org.jire.overwatcheat.nativelib

import java.lang.foreign.*

object User32Panama {

val linker = Linker.nativeLinker()
val user32 = SymbolLookup.libraryLookup("User32", MemorySession.global())
val getKeyState = linker.downcallHandle(
user32.lookup("GetKeyState").get(),
FunctionDescriptor.of(ValueLayout.JAVA_SHORT, ValueLayout.JAVA_INT)
)

fun GetKeyState(nVirtKey: Int): Short = getKeyState.invokeExact(nVirtKey) as Short

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Free, open-source undetected color cheat for Overwatch!
* Copyright (C) 2017 Thomas G. Nappo
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package org.jire.overwatcheat.nativelib.interception

import java.lang.foreign.*

object InterceptionPanama {

val linker = Linker.nativeLinker()
val interception = SymbolLookup.libraryLookup("interception", MemorySession.global())

private val interception_create_context = linker.downcallHandle(
interception.lookup("interception_create_context").get(),
FunctionDescriptor.of(ValueLayout.ADDRESS)
)

fun interception_create_context() = interception_create_context.invokeExact() as MemoryAddress

val interceptionMouseStrokeLayout: GroupLayout = MemoryLayout.structLayout(
ValueLayout.JAVA_SHORT,
ValueLayout.JAVA_SHORT,
ValueLayout.JAVA_SHORT,
ValueLayout.JAVA_INT,
ValueLayout.JAVA_INT,
ValueLayout.JAVA_INT
)

private val interception_send = linker.downcallHandle(
interception.lookup("interception_send").get(),
FunctionDescriptor.of(
ValueLayout.JAVA_INT,
ValueLayout.ADDRESS, ValueLayout.JAVA_INT, interceptionMouseStrokeLayout, ValueLayout.JAVA_INT
)
)

fun interception_send(context: Addressable, device: Int, stroke: MemorySegment, nstroke: Int) =
interception_send.invokeExact(
context,
device,
stroke,
nstroke
) as Int

}
32 changes: 32 additions & 0 deletions src/main/kotlin/org/jire/overwatcheat/util/Threads.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Free, open-source undetected color cheat for Overwatch!
* Copyright (C) 2017 Thomas G. Nappo
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package org.jire.overwatcheat.util

object Threads {

fun preciseSleep(totalNanos: Long) {
val startTime = System.nanoTime()

// busy-waiting
while (System.nanoTime() - startTime < totalNanos) {
Thread.onSpinWait()
}
}

}

0 comments on commit a5dcf05

Please sign in to comment.