Skip to content

Commit a4eb15c

Browse files
committed
Initial Commit
0 parents  commit a4eb15c

File tree

19 files changed

+830
-0
lines changed

19 files changed

+830
-0
lines changed

.github/workflows/client.yaml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
name: Build Client
2+
3+
on:
4+
push:
5+
6+
jobs:
7+
build:
8+
runs-on: windows-latest
9+
steps:
10+
- uses: actions/checkout@v4
11+
- uses: actions/setup-java@v4
12+
with:
13+
distribution: "temurin"
14+
java-version: "23"
15+
- uses: gradle/actions/setup-gradle@v4
16+
- run: ./gradlew client:packageDist
17+
- name: Release
18+
uses: softprops/action-gh-release@v2
19+
if: ${{ github.ref == 'refs/heads/main' }}
20+
with:
21+
tag_name: ${{ github.run_number }}
22+
files: client/dist/*.zip

.github/workflows/server.yaml

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
name: Docker
2+
3+
on:
4+
push:
5+
pull_request:
6+
7+
env:
8+
REGISTRY: ghcr.io
9+
IMAGE_NAME: ${{ github.repository }}
10+
11+
jobs:
12+
build:
13+
runs-on: ubuntu-latest
14+
permissions:
15+
contents: read
16+
packages: write
17+
18+
steps:
19+
- name: Checkout repository
20+
uses: actions/checkout@v4
21+
- uses: actions/setup-java@v4
22+
with:
23+
java-version: 23
24+
distribution: temurin
25+
- uses: gradle/actions/setup-gradle@v4
26+
- run: ./gradlew server:installDist
27+
- name: Setup Docker buildx
28+
uses: docker/setup-buildx-action@v3
29+
- name: Log into registry ${{ env.REGISTRY }}
30+
if: github.event_name != 'pull_request'
31+
uses: docker/login-action@v3
32+
with:
33+
registry: ${{ env.REGISTRY }}
34+
username: ${{ github.actor }}
35+
password: ${{ secrets.GITHUB_TOKEN }}
36+
- name: Extract Docker metadata
37+
id: meta
38+
uses: docker/metadata-action@v5
39+
with:
40+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
41+
tags: |
42+
type=ref,event=branch
43+
type=sha
44+
flavor: latest=${{ github.ref == 'refs/heads/main' }}
45+
46+
- name: Build and push Docker image
47+
id: build-and-push
48+
uses: docker/build-push-action@v6
49+
with:
50+
context: server
51+
push: ${{ github.event_name != 'pull_request' }}
52+
tags: ${{ steps.meta.outputs.tags }}
53+
labels: ${{ steps.meta.outputs.labels }}
54+
platforms: linux/amd64, linux/arm64
55+
cache-from: type=gha
56+
cache-to: type=gha,mode=max

.gitignore

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
# Created by https://www.toptal.com/developers/gitignore/api/intellij+all,gradle
2+
# Edit at https://www.toptal.com/developers/gitignore?templates=intellij+all,gradle
3+
4+
### Intellij+all ###
5+
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
6+
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
7+
8+
# User-specific stuff
9+
.idea/**/workspace.xml
10+
.idea/**/tasks.xml
11+
.idea/**/usage.statistics.xml
12+
.idea/**/dictionaries
13+
.idea/**/shelf
14+
15+
# AWS User-specific
16+
.idea/**/aws.xml
17+
18+
# Generated files
19+
.idea/**/contentModel.xml
20+
21+
# Sensitive or high-churn files
22+
.idea/**/dataSources/
23+
.idea/**/dataSources.ids
24+
.idea/**/dataSources.local.xml
25+
.idea/**/sqlDataSources.xml
26+
.idea/**/dynamic.xml
27+
.idea/**/uiDesigner.xml
28+
.idea/**/dbnavigator.xml
29+
30+
# Gradle
31+
.idea/**/gradle.xml
32+
.idea/**/libraries
33+
34+
# Gradle and Maven with auto-import
35+
# When using Gradle or Maven with auto-import, you should exclude module files,
36+
# since they will be recreated, and may cause churn. Uncomment if using
37+
# auto-import.
38+
# .idea/artifacts
39+
# .idea/compiler.xml
40+
# .idea/jarRepositories.xml
41+
# .idea/modules.xml
42+
# .idea/*.iml
43+
# .idea/modules
44+
# *.iml
45+
# *.ipr
46+
47+
# CMake
48+
cmake-build-*/
49+
50+
# Mongo Explorer plugin
51+
.idea/**/mongoSettings.xml
52+
53+
# File-based project format
54+
*.iws
55+
56+
# IntelliJ
57+
out/
58+
59+
# mpeltonen/sbt-idea plugin
60+
.idea_modules/
61+
62+
# JIRA plugin
63+
atlassian-ide-plugin.xml
64+
65+
# Cursive Clojure plugin
66+
.idea/replstate.xml
67+
68+
# SonarLint plugin
69+
.idea/sonarlint/
70+
71+
# Crashlytics plugin (for Android Studio and IntelliJ)
72+
com_crashlytics_export_strings.xml
73+
crashlytics.properties
74+
crashlytics-build.properties
75+
fabric.properties
76+
77+
# Editor-based Rest Client
78+
.idea/httpRequests
79+
80+
# Android studio 3.1+ serialized cache file
81+
.idea/caches/build_file_checksums.ser
82+
83+
### Intellij+all Patch ###
84+
# Ignore everything but code style settings and run configurations
85+
# that are supposed to be shared within teams.
86+
87+
.idea/*
88+
89+
!.idea/codeStyles
90+
!.idea/runConfigurations
91+
92+
### Gradle ###
93+
.gradle
94+
**/build/
95+
!src/**/build/
96+
97+
# Ignore Gradle GUI config
98+
gradle-app.setting
99+
100+
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
101+
!gradle-wrapper.jar
102+
103+
# Avoid ignore Gradle wrappper properties
104+
!gradle-wrapper.properties
105+
106+
# Cache of project
107+
.gradletasknamecache
108+
109+
# Eclipse Gradle plugin generated files
110+
# Eclipse Core
111+
.project
112+
# JDT-specific (Eclipse Java Development Tools)
113+
.classpath
114+
115+
### Gradle Patch ###
116+
# Java heap dump
117+
*.hprof
118+
119+
# End of https://www.toptal.com/developers/gitignore/api/intellij+all,gradle

README.md

Whitespace-only changes.

buildSrc/build.gradle.kts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
plugins {
2+
// The Kotlin DSL plugin provides a convenient way to develop convention plugins.
3+
// Convention plugins are located in `src/main/kotlin`, with the file extension `.gradle.kts`,
4+
// and are applied in the project's `build.gradle.kts` files as required.
5+
`kotlin-dsl`
6+
}
7+
8+
kotlin {
9+
jvmToolchain(22)
10+
}
11+
12+
dependencies {
13+
// Add a dependency on the Kotlin Gradle plugin, so that convention plugins can apply it.
14+
implementation(libs.kotlinGradlePlugin)
15+
}

buildSrc/settings.gradle.kts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
dependencyResolutionManagement {
2+
3+
// Use Maven Central and the Gradle Plugin Portal for resolving dependencies in the shared build logic (`buildSrc`) project.
4+
@Suppress("UnstableApiUsage")
5+
repositories {
6+
mavenCentral()
7+
}
8+
9+
// Reuse the version catalog from the main build.
10+
versionCatalogs {
11+
create("libs") {
12+
from(files("../gradle/libs.versions.toml"))
13+
}
14+
}
15+
}
16+
17+
rootProject.name = "buildSrc"
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// The code in this file is a convention plugin - a Gradle mechanism for sharing reusable build logic.
2+
// `buildSrc` is a Gradle-recognized directory and every plugin there will be easily available in the rest of the build.
3+
package buildsrc.convention
4+
5+
import org.gradle.api.tasks.testing.logging.TestLogEvent
6+
7+
plugins {
8+
// Apply the Kotlin JVM plugin to add support for Kotlin in JVM projects.
9+
kotlin("jvm")
10+
}
11+
12+
kotlin {
13+
// Use a specific Java version to make it easier to work in different environments.
14+
jvmToolchain(22)
15+
}

client/build.gradle.kts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import org.panteleyev.jpackage.ImageType
2+
3+
plugins {
4+
id("buildsrc.convention.kotlin-jvm")
5+
id("org.panteleyev.jpackageplugin") version "1.6.1"
6+
}
7+
8+
version = "1.0.0"
9+
10+
dependencies {
11+
implementation(libs.jnativehook)
12+
implementation(libs.ktor.client.okhttp)
13+
implementation(libs.ktor.client.websockets)
14+
implementation(libs.slf4j.simple)
15+
}
16+
17+
tasks {
18+
val copyDependencies = registering(Copy::class) {
19+
from(configurations.runtimeClasspath).into(layout.buildDirectory.dir("jars"))
20+
}
21+
22+
val copyJar = registering(Copy::class) {
23+
from(jar).into(layout.buildDirectory.dir("jars"))
24+
}
25+
26+
jpackage {
27+
dependsOn(build, copyDependencies, copyJar)
28+
winConsole = true
29+
30+
input = layout.buildDirectory.dir("jars").get().asFile.absolutePath
31+
32+
appName = "GTA KILL"
33+
vendor = "Schlaubi"
34+
type = ImageType.APP_IMAGE
35+
36+
mainJar = jar.get().archiveFile.get().asFile.absolutePath
37+
mainClass = "dev.schlaubi.mastermind.MainKt"
38+
39+
destination = layout.buildDirectory.dir("dist").get().asFile.absolutePath
40+
}
41+
42+
register<Tar>("packageDist") {
43+
from(jpackage)
44+
45+
compression = Compression.GZIP
46+
archiveExtension = "tar.gz"
47+
destinationDirectory = layout.buildDirectory.dir("dist")
48+
}
49+
}

client/src/main/kotlin/Main.kt

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package dev.schlaubi.mastermind
2+
3+
import com.github.kwhat.jnativehook.GlobalScreen
4+
import com.github.kwhat.jnativehook.keyboard.NativeKeyEvent
5+
import com.github.kwhat.jnativehook.keyboard.NativeKeyListener
6+
import io.ktor.client.*
7+
import io.ktor.client.plugins.websocket.*
8+
import io.ktor.websocket.*
9+
import kotlinx.coroutines.*
10+
import java.util.concurrent.Executors
11+
import kotlin.jvm.optionals.getOrNull
12+
import kotlin.time.Duration.Companion.seconds
13+
14+
private lateinit var session: DefaultClientWebSocketSession
15+
16+
private val LoomDispatcher = Executors
17+
.newVirtualThreadPerTaskExecutor().asCoroutineDispatcher()
18+
19+
private val client = HttpClient {
20+
install(WebSockets) {
21+
pingInterval = 15.seconds
22+
}
23+
}
24+
25+
private fun CoroutineScope.connect() {
26+
launch {
27+
session = client.webSocketSession("ws://haxis.me:5000")
28+
29+
println("Connection established")
30+
for (frame in session.incoming) {
31+
println("Got frame: $frame")
32+
val incoming = (frame as? Frame.Text)?.readText() ?: continue
33+
println("Got frame text: $incoming")
34+
if (incoming == "KILL_GTA") {
35+
kill()
36+
}
37+
}
38+
39+
println("Connection closed, trying to reconnect")
40+
41+
connect()
42+
}
43+
}
44+
45+
suspend fun main() = coroutineScope {
46+
connect()
47+
48+
GlobalScreen.registerNativeHook()
49+
50+
GlobalScreen.addNativeKeyListener(object : NativeKeyListener {
51+
override fun nativeKeyPressed(nativeEvent: NativeKeyEvent) {
52+
if (nativeEvent.keyCode == NativeKeyEvent.VC_F3) {
53+
println("F3 pressed, sending kill command")
54+
55+
runBlocking(LoomDispatcher) { reportAndKill() }
56+
}
57+
}
58+
})
59+
}
60+
61+
private fun kill() {
62+
println("Trying to kill GTA5.exe")
63+
64+
val gtaProcess = ProcessHandle.allProcesses()
65+
.filter { it.info().command().getOrNull()?.contains("GTA5.exe") == true }
66+
.findFirst()
67+
if (gtaProcess.isPresent) {
68+
gtaProcess.get().destroyForcibly()
69+
} else {
70+
println("GTA5.exe not found")
71+
}
72+
}
73+
74+
private suspend fun report() {
75+
session.outgoing.send(Frame.Text("KILL_GTA"))
76+
}
77+
78+
private suspend fun reportAndKill() {
79+
kill()
80+
report()
81+
}

gradle.properties

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Enable the build cache to save time by reusing outputs produced by other successful builds.
2+
# https://docs.gradle.org/current/userguide/build_cache.html
3+
org.gradle.caching=true
4+
# Enable the configuration cache to reuse the build configuration and enable parallel task execution.
5+
# (Note that some plugins may not yet be compatible with the configuration cache.)
6+
# https://docs.gradle.org/current/userguide/configuration_cache.html
7+
org.gradle.configuration-cache=true

0 commit comments

Comments
 (0)