Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
5be45be
Initial push of a new Depot Downloader
LossyDragon Oct 3, 2025
873266a
Clean up dependencies
LossyDragon Oct 3, 2025
1918b7c
Finalize some methods, and some cleanup.
LossyDragon Oct 3, 2025
e9a9079
Fix nullable value in ConcurrentHashMap
LossyDragon Oct 3, 2025
e3521aa
Some tidying
LossyDragon Oct 4, 2025
b0dc78b
Add maven and update workflows
LossyDragon Oct 4, 2025
dc68c22
Rename ContentDownloader and ContentDownloaderException to DepotDownl…
LossyDragon Oct 5, 2025
a9aa8d8
Simplify SampleDownloadApp
LossyDragon Oct 5, 2025
c2e9e24
A litte more tidying
LossyDragon Oct 6, 2025
5e88d24
Fix getting sha file
LossyDragon Oct 13, 2025
3dd1b11
Simplify IDownloadListener, fix up DepotDownloader yielding. Update S…
LossyDragon Oct 13, 2025
2a92260
Bump version
LossyDragon Oct 13, 2025
e0c2515
Add reified method for removeHandler.
LossyDragon Oct 13, 2025
8cfab8a
Add reified method for addHandler.
LossyDragon Oct 14, 2025
82e25f0
Fix OOM on android when allocating a file.
LossyDragon Nov 14, 2025
a4fd323
Allow getting more servers in getServersForSteamPipe
LossyDragon Nov 14, 2025
4005a69
Add basic support for downloading Workshop collections
LossyDragon Nov 14, 2025
89db275
Add some more logs
LossyDragon Nov 18, 2025
35da399
Actually populate packageTokens.
LossyDragon Nov 18, 2025
415e584
use okhttp timeouts, optimize a performance chokepoint in manifest se…
LossyDragon Nov 19, 2025
5f96c35
Temp work around. Don't cancel on a depot that has no manifest reques…
LossyDragon Nov 20, 2025
c52354c
Clarify some error logs.
LossyDragon Dec 1, 2025
0af6df6
Properly install games based on install directory name.
LossyDragon Dec 1, 2025
a101526
Added onChunkCompleted callback
Dec 2, 2025
bfd5659
Add Client Communication for remote control. Add some methods to Stea…
LossyDragon Dec 17, 2025
5ca6159
Add annotations to new code.
LossyDragon Dec 17, 2025
c2b8dbd
Complete todos, add and revice kdoc
LossyDragon Dec 17, 2025
6a947c4
Add kdoc to SteamContent.getDepotPatchInfo
LossyDragon Dec 17, 2025
e8afafc
add clientInstanceId to login response, other tweaks.
LossyDragon Dec 18, 2025
7eba1c7
Add maxFileWrites, separate download and file write operation to impr…
joshuatam Dec 9, 2025
f747e4e
change notifyListeners to use coroutineScope for non blocking call to…
joshuatam Dec 9, 2025
c4d3d4c
changed to use pre-launch file workers for better I/O performance
joshuatam Dec 10, 2025
6137597
update notifyListeners to run on main thread instead launching other …
joshuatam Dec 15, 2025
7f66ba2
Revert "update notifyListeners to run on main thread instead launchin…
joshuatam Dec 15, 2025
66fe3cf
Improves concurrent depot downloading
joshuatam Dec 16, 2025
d9d0071
Lint formatting
LossyDragon Dec 16, 2025
5cdb774
Refactors chunk processing with Flows
joshuatam Dec 17, 2025
5455bb2
Updates exception handling in CDN client
joshuatam Dec 17, 2025
61257af
Lint fix: imports specific Kotlin flow
joshuatam Dec 17, 2025
571755b
Fix lexicographic order
LossyDragon Dec 17, 2025
3cbf9db
Changes dispatcher for download task
joshuatam Dec 19, 2025
0cd6d13
Adds parent job cancellation support
joshuatam Dec 19, 2025
d5db49f
Lint cleanup
LossyDragon Dec 23, 2025
86caf17
Prepare for release
LossyDragon Dec 24, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/javasteam-build-push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,7 @@ jobs:
with:
name: javasteam-tf
path: javasteam-tf/build/libs
- uses: actions/upload-artifact@v4
with:
name: javasteam-depotdownloader
path: javasteam-depotdownloader/build/libs
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,9 @@ loginkey.txt
sentry.bin
server_list.bin
/steamapps/
/depots/
/userfiles/
refreshtoken.txt

# Kotlin 2.0
/.kotlin/sessions/
Expand Down
4 changes: 2 additions & 2 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ plugins {

allprojects {
group = "in.dragonbra"
version = "1.7.1-SNAPSHOT"
version = "1.8.0"
}

repositories {
Expand Down Expand Up @@ -150,10 +150,10 @@ dependencies {
mockitoAgent(libs.test.mock.core) { isTransitive = false }

implementation(libs.bundles.ktor)
implementation(libs.bundles.okHttp)
implementation(libs.commons.lang3)
implementation(libs.kotlin.coroutines)
implementation(libs.kotlin.stdib)
implementation(libs.okHttp)
implementation(libs.protobuf.java)
compileOnly(libs.xz)
compileOnly(libs.zstd)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class ProtoParser(private val outputDir: File) {
private val suppressAnnotation = AnnotationSpec
.builder(Suppress::class)
.addMember("%S", "KDocUnresolvedReference") // IntelliJ's seems to get confused with canonical names
.addMember("%S", "RemoveRedundantQualifierName") // Full Qualifier names are fine
.addMember("%S", "RedundantVisibilityModifier") // KotlinPoet is an explicit API generator
.addMember("%S", "unused") // All methods could be used.
.build()
Expand Down Expand Up @@ -85,6 +86,8 @@ class ProtoParser(private val outputDir: File) {
private fun buildClass(file: File, service: Service) {
val protoFileName = transformProtoFileName(file.name)

val parentPathName = file.parentFile.name

// Class Builder
val steamUnifiedMessagesClassName = ClassName(
"in.dragonbra.javasteam.steam.handlers.steamunifiedmessages",
Expand Down Expand Up @@ -129,7 +132,7 @@ class ProtoParser(private val outputDir: File) {
// HAS Response
numResponse++
val className = ClassName(
packageName = "in.dragonbra.javasteam.protobufs.steamclient.$protoFileName",
packageName = "in.dragonbra.javasteam.protobufs.$parentPathName.$protoFileName",
method.responseType
)
responseBlock.addStatement(
Expand All @@ -141,7 +144,7 @@ class ProtoParser(private val outputDir: File) {
// NO Response
numNotification++
val className = ClassName(
packageName = "in.dragonbra.javasteam.protobufs.steamclient.$protoFileName",
packageName = "in.dragonbra.javasteam.protobufs.$parentPathName.$protoFileName",
method.requestType
)
notificationBlock.addStatement(
Expand Down Expand Up @@ -192,7 +195,7 @@ class ProtoParser(private val outputDir: File) {
.addParameter(
"request",
ClassName(
packageName = "in.dragonbra.javasteam.protobufs.steamclient.$protoFileName",
packageName = "in.dragonbra.javasteam.protobufs.$parentPathName.$protoFileName",
method.requestType
)
)
Expand All @@ -207,14 +210,14 @@ class ProtoParser(private val outputDir: File) {
packageName = "in.dragonbra.javasteam.steam.handlers.steamunifiedmessages.callback",
"ServiceMethodResponse"
).parameterizedBy(
ClassName.bestGuess("in.dragonbra.javasteam.protobufs.steamclient.$protoFileName.${method.responseType}.Builder")
ClassName.bestGuess("in.dragonbra.javasteam.protobufs.$parentPathName.$protoFileName.${method.responseType}.Builder")
)
)
)
funcBuilder.addStatement(
format = "return unifiedMessages!!.sendMessage(\n%T.Builder::class.java,\n%S,\nrequest\n)",
ClassName(
packageName = "in.dragonbra.javasteam.protobufs.steamclient.$protoFileName",
packageName = "in.dragonbra.javasteam.protobufs.$parentPathName.$protoFileName",
method.responseType
),
"${service.name}.${method.methodName}#1"
Expand All @@ -223,7 +226,7 @@ class ProtoParser(private val outputDir: File) {
funcBuilder.addStatement(
format = "unifiedMessages!!.sendNotification<%T.Builder>(\n%S,\nrequest\n)",
ClassName(
packageName = "in.dragonbra.javasteam.protobufs.steamclient.$protoFileName",
packageName = "in.dragonbra.javasteam.protobufs.$parentPathName.$protoFileName",
method.requestType
),
"${service.name}.${method.methodName}#1"
Expand Down
15 changes: 15 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ publishPlugin = "2.0.0" # https://mvnrepository.com/artifact/io.github.gradle-ne
xz = "1.11" # https://mvnrepository.com/artifact/org.tukaani/xz
zstd = "1.5.7-6" # https://search.maven.org/artifact/com.github.luben/zstd-jni

# Depot Downloader
kotlin-serialization-json = "1.9.0" # https://mvnrepository.com/artifact/org.jetbrains.kotlinx/kotlinx-serialization-json-jvm
okio = "3.16.0" # https://mvnrepository.com/artifact/com.squareup.okio/okio

# Testing Lib versions
commons-io = "2.21.0" # https://mvnrepository.com/artifact/commons-io/commons-io
commonsCodec = "1.20.0" # https://mvnrepository.com/artifact/commons-codec/commons-codec
Expand All @@ -41,11 +45,16 @@ ktor-client-cio = { module = "io.ktor:ktor-client-cio", version.ref = "ktor" }
ktor-client-core = { module = "io.ktor:ktor-client-core", version.ref = "ktor" }
ktor-client-websocket = { module = "io.ktor:ktor-client-websockets", version.ref = "ktor" }
okHttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okHttp" }
okHttp-coroutines = { module = "com.squareup.okhttp3:okhttp-coroutines", version.ref = "okHttp" }
protobuf-java = { module = "com.google.protobuf:protobuf-java", version.ref = "protobuf" }
protobuf-protoc = { module = "com.google.protobuf:protoc", version.ref = "protobuf" }
xz = { module = "org.tukaani:xz", version.ref = "xz" }
zstd = { module = "com.github.luben:zstd-jni", version.ref = "zstd" }

# Depot Downloader
kotlin-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlin-serialization-json"}
okio = { module = "com.squareup.okio:okio", version.ref = "okio"}

# Tests
test-commons-codec = { module = "commons-codec:commons-codec", version.ref = "commonsCodec" }
test-commons-io = { module = "commons-io:commons-io", version.ref = "commons-io" }
Expand All @@ -65,6 +74,7 @@ qrCode = { module = "pro.leaco.qrcode:console-qrcode", version.ref = "qrCode" }
kotlin-dokka = { id = "org.jetbrains.dokka", version.ref = "dokka" }
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
kotlin-kotlinter = { id = "org.jmailen.kotlinter", version.ref = "kotlinter" }
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
maven-publish = { id = "io.github.gradle-nexus.publish-plugin", version.ref = "publishPlugin" }
protobuf-gradle = { id = "com.google.protobuf", version.ref = "protobuf-gradle" }

Expand All @@ -86,3 +96,8 @@ ktor = [
"ktor-client-cio",
"ktor-client-websocket",
]

okHttp = [
"okHttp",
"okHttp-coroutines",
]
1 change: 1 addition & 0 deletions javasteam-depotdownloader/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build/
116 changes: 116 additions & 0 deletions javasteam-depotdownloader/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import org.gradle.kotlin.dsl.withType
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jmailen.gradle.kotlinter.tasks.FormatTask
import org.jmailen.gradle.kotlinter.tasks.LintTask

plugins {
alias(libs.plugins.kotlin.dokka)
alias(libs.plugins.kotlin.jvm)
alias(libs.plugins.kotlin.kotlinter)
alias(libs.plugins.kotlin.serialization)
alias(libs.plugins.protobuf.gradle)
id("maven-publish")
id("signing")
}

repositories {
mavenCentral()
}

kotlin {
compilerOptions {
jvmTarget.set(JvmTarget.fromTarget(libs.versions.java.get()))
}
}

/* Protobufs */
protobuf.protoc {
artifact = libs.protobuf.protoc.get().toString()
}

java {
sourceCompatibility = JavaVersion.toVersion(libs.versions.java.get())
targetCompatibility = JavaVersion.toVersion(libs.versions.java.get())
withSourcesJar()
}

/* Java-Kotlin Docs */
dokka {
moduleName.set("JavaSteam")
dokkaSourceSets.main {
suppressGeneratedFiles.set(false) // Allow generated files to be documented.
perPackageOption {
// Deny most of the generated files.
matchingRegex.set("in.dragonbra.javasteam.(protobufs|enums|generated).*")
suppress.set(true)
}
}
}

// Make sure Maven Publishing gets javadoc
val javadocJar by tasks.registering(Jar::class) {
dependsOn(tasks.dokkaGenerate)
archiveClassifier.set("javadoc")
from(layout.buildDirectory.dir("dokka/html"))
}
artifacts {
archives(javadocJar)
}

/* Kotlinter */
tasks.withType<LintTask> {
this.source = this.source.minus(fileTree("build/generated")).asFileTree
}
tasks.withType<FormatTask> {
this.source = this.source.minus(fileTree("build/generated")).asFileTree
}

dependencies {
implementation(rootProject)

implementation(libs.bundles.ktor)
implementation(libs.commons.lang3)
implementation(libs.kotlin.coroutines)
implementation(libs.kotlin.serialization.json)
implementation(libs.kotlin.stdib)
implementation(libs.okio)
implementation(libs.protobuf.java)
}

/* Artifact publishing */
publishing {
publications {
create<MavenPublication>("mavenJava") {
from(components["java"])
pom {
name = "JavaSteam-depotdownloader"
packaging = "jar"
description = "Depot Downloader for JavaSteam."
url = "https://github.com/Longi94/JavaSteam"
inceptionYear = "2025"
scm {
connection = "scm:git:git://github.com/Longi94/JavaSteam.git"
developerConnection = "scm:git:ssh://github.com:Longi94/JavaSteam.git"
url = "https://github.com/Longi94/JavaSteam/tree/master"
}
licenses {
license {
name = "MIT License"
url = "https://www.opensource.org/licenses/mit-license.php"
}
}
developers {
developer {
id = "Longi"
name = "Long Tran"
email = "lngtrn94@gmail.com"
}
}
}
}
}
}

signing {
sign(publishing.publications["mavenJava"])
}
Loading