👋 Welcome to the AquaTrans™ server data transfer tool!
+
You can use this to export data from any server, and input data into any server using the connection credentials (card number, server address, and keychip id).
+
This tool will simulate a game client and pull your data from the source server, and push your data to the destination server.
+ {#each messages.slice(Math.max(messages.length - 5, 0), undefined) as msg}
+
{msg}
+ {/each}
+
+ {/if}
+
+
+
+ {#if !tested}
+
+ {:else}
+
+
+ {/if}
+
+
+
+
diff --git a/build.gradle.kts b/build.gradle.kts
index 41d937d7..510a4674 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -4,7 +4,7 @@ import java.time.ZoneId
import java.time.format.DateTimeFormatter
plugins {
- val ktVer = "2.1.0"
+ val ktVer = "2.1.10"
java
kotlin("plugin.lombok") version ktVer
@@ -117,6 +117,10 @@ springBoot {
mainClass.set("icu.samnyan.aqua.EntryKt")
}
+application {
+ mainClass = "icu.samnyan.aqua.EntryKt"
+}
+
hibernate {
enhancement {
enableLazyInitialization = true
diff --git a/docs/self-hosting.md b/docs/self-hosting.md
index 83522f9d..057eec5c 100644
--- a/docs/self-hosting.md
+++ b/docs/self-hosting.md
@@ -14,7 +14,7 @@ and change `allnet.server.host` to your LAN IP address (e.g. 192.168.0.?). You c
> [!NOTE]
> The guide above will create a new MariaDB database.
-> If you were using SQLite Aqua before, it is not supported in AquaDX. Please export your data and import it to MariaDB.
+> If you were using SQLite Aqua before, it is not supported in AquaDX. Please export your data and import it to your new instance.
> If you were using MySQL Aqua before, you can migrate to MariaDB using [this guide here](docs/mysql_to_mariadb.md).
### Configuration
@@ -42,3 +42,9 @@ docker compose up
### Building
You need to install JDK 21 on your system, then run `./gradlew clean build`. The jar file will be built into the `build/libs` folder.
+
+## Why drop SQLite support?
+
+If you wonder why I dropped SQLite support, ask SQLite devs why they still haven't supported adding a single constraint to a table without all the hassle of creating a new one and migrating all data over and finally deleting the original.
+
+
\ No newline at end of file
diff --git a/docs/sqlite-sucks.png b/docs/sqlite-sucks.png
new file mode 100644
index 00000000..0d32dcd8
Binary files /dev/null and b/docs/sqlite-sucks.png differ
diff --git a/src/main/java/ext/Ext.kt b/src/main/java/ext/Ext.kt
index c7278dcc..9f6e1ca2 100644
--- a/src/main/java/ext/Ext.kt
+++ b/src/main/java/ext/Ext.kt
@@ -192,8 +192,7 @@ val Any?.str get() = toString()
// Collections
fun ls(vararg args: T) = args.toList()
inline fun arr(vararg args: T) = arrayOf(*args)
-operator fun Map.plus(map: Map) =
- (if (this is MutableMap) this else mut).apply { putAll(map) }
+operator fun Map.plus(map: Map) = mut.apply { putAll(map) }
operator fun MutableMap.plusAssign(map: Map) { putAll(map) }
fun Map.vNotNull(): Map = filterValues { it != null }.mapValues { it.value!! }
fun MutableList.popAll(list: List) = list.also { removeAll(it) }
@@ -238,6 +237,7 @@ fun Str.path() = Path.of(this)
operator fun Path.div(part: Str) = resolve(part)
operator fun File.div(fileName: Str) = File(this, fileName)
fun Str.ensureEndingSlash() = if (endsWith('/')) this else "$this/"
+fun Str.ensureNoEndingSlash() = if (endsWith('/')) dropLast(1) else this
fun T.logger() = LoggerFactory.getLogger(this::class.java)
diff --git a/src/main/java/ext/Http.kt b/src/main/java/ext/Http.kt
new file mode 100644
index 00000000..d0c73fe7
--- /dev/null
+++ b/src/main/java/ext/Http.kt
@@ -0,0 +1,34 @@
+package ext
+
+import icu.samnyan.aqua.sega.util.ZLib
+import java.net.URI
+import java.net.http.HttpClient
+import java.net.http.HttpRequest
+import java.net.http.HttpResponse
+
+val client = HttpClient.newBuilder().build()
+
+fun HttpRequest.Builder.send() = client.send(this.build(), HttpResponse.BodyHandlers.ofByteArray())
+fun HttpRequest.Builder.header(pair: Pair) = this.header(pair.first.toString(), pair.second.toString())
+fun String.request() = HttpRequest.newBuilder(URI.create(this))
+
+fun HttpRequest.Builder.post(body: Any? = null) = this.POST(when (body) {
+ is ByteArray -> HttpRequest.BodyPublishers.ofByteArray(body)
+ is String -> HttpRequest.BodyPublishers.ofString(body)
+ is HttpRequest.BodyPublisher -> body
+ else -> throw Exception("Unsupported body type")
+}).send()
+
+
+inline fun HttpResponse.json(): T? = body()?.json()
+
+fun HttpRequest.Builder.postZ(body: String) = run {
+ header("Content-Type" to "application/json")
+ header("Content-Encoding" to "deflate")
+ post(ZLib.compress(body.toByteArray()))
+}
+
+fun HttpResponse.header(key: String) = headers().firstValue(key).orElse(null)
+fun HttpResponse.bodyString() = body()?.toString(Charsets.UTF_8)
+fun HttpResponse.bodyZ() = body()?.let { ZLib.decompress(it)?.decodeToString() }
+fun HttpResponse.bodyMaybeZ() = if (header("Content-Encoding") == "deflate") bodyZ() else bodyString()
diff --git a/src/main/java/ext/Json.kt b/src/main/java/ext/Json.kt
index 964b3b38..61cd6545 100644
--- a/src/main/java/ext/Json.kt
+++ b/src/main/java/ext/Json.kt
@@ -43,16 +43,18 @@ else JACKSON.readValue(this, cls)
fun T.toJson() = JACKSON.writeValueAsString(this)
inline fun String.json() = try {
- JACKSON.readValue(this, T::class.java)
+ if (isEmpty() || this == "null") null
+ else JACKSON.readValue(this, T::class.java)
}
catch (e: Exception) {
println("Failed to parse JSON: $this")
throw e
}
-fun String.jsonMap(): Map = json()
-fun String.jsonArray(): List