Initial commit
This commit is contained in:
150
build.gradle.kts
Normal file
150
build.gradle.kts
Normal file
@@ -0,0 +1,150 @@
|
||||
import java.util.zip.CRC32
|
||||
import java.util.zip.ZipEntry
|
||||
import java.util.zip.ZipFile
|
||||
import java.util.zip.ZipOutputStream
|
||||
|
||||
// Text file extensions for LF normalization
|
||||
val textExtensions = setOf(".kt", ".java", ".properties", ".json", ".toml", ".xml", ".txt", ".MF")
|
||||
fun isTextFile(name: String) = textExtensions.any { name.endsWith(it) } || name.startsWith("META-INF/services/")
|
||||
|
||||
fun normalizeContent(name: String, content: ByteArray): ByteArray {
|
||||
if (!isTextFile(name)) return content
|
||||
return content.toString(Charsets.UTF_8)
|
||||
.replace("\r\n", "\n").replace("\r", "\n")
|
||||
.toByteArray(Charsets.UTF_8)
|
||||
}
|
||||
|
||||
fun writeStoredEntry(output: ZipOutputStream, name: String, content: ByteArray) {
|
||||
val normalized = normalizeContent(name, content)
|
||||
val entry = ZipEntry(name).apply {
|
||||
time = 0
|
||||
size = normalized.size.toLong()
|
||||
compressedSize = normalized.size.toLong()
|
||||
crc = CRC32().apply { update(normalized) }.value
|
||||
method = ZipEntry.STORED
|
||||
}
|
||||
output.putNextEntry(entry)
|
||||
output.write(normalized)
|
||||
output.closeEntry()
|
||||
}
|
||||
|
||||
plugins {
|
||||
id("java")
|
||||
}
|
||||
|
||||
java {
|
||||
toolchain {
|
||||
languageVersion.set(JavaLanguageVersion.of(21))
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven {
|
||||
name = "hytale-release"
|
||||
url = uri("https://maven.hytale.com/release")
|
||||
}
|
||||
maven {
|
||||
name = "hytale-pre-release"
|
||||
url = uri("https://maven.hytale.com/pre-release")
|
||||
}
|
||||
}
|
||||
|
||||
val hytaleServer: Configuration by configurations.creating
|
||||
|
||||
val patchedJar = rootDir.resolve("repo/applications/HytaleServerPatched.jar")
|
||||
|
||||
dependencies {
|
||||
hytaleServer("com.hypixel.hytale:Server:2026.01.22-6f8bdbdc4")
|
||||
}
|
||||
|
||||
configurations {
|
||||
compileOnly.get().extendsFrom(hytaleServer)
|
||||
}
|
||||
|
||||
tasks.withType<JavaCompile> {
|
||||
options.compilerArgs.addAll(listOf(
|
||||
"--add-exports", "java.base/jdk.internal.vm.annotation=ALL-UNNAMED"
|
||||
))
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
java {
|
||||
// Patch files go in runtime/hytale-server/src/
|
||||
// Use the same package structure as the original JAR
|
||||
// e.g., src/com/hypixel/hytale/server/SomeClass.java
|
||||
srcDir("src")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Task to create the patched JAR by overlaying compiled classes on top of original
|
||||
tasks.register("patchJar") {
|
||||
group = "coldfusion"
|
||||
description = "Creates a patched HytaleServer JAR with compiled modifications"
|
||||
|
||||
dependsOn(tasks.compileJava)
|
||||
|
||||
inputs.files(hytaleServer)
|
||||
inputs.files(tasks.compileJava.get().outputs.files).optional()
|
||||
outputs.file(patchedJar)
|
||||
|
||||
doLast {
|
||||
val compiledClassesDir = tasks.compileJava.get().destinationDirectory.get().asFile
|
||||
val originalJar = hytaleServer.singleFile
|
||||
|
||||
// Collect all compiled class files with their relative paths
|
||||
val patchedFiles = mutableMapOf<String, ByteArray>()
|
||||
if (compiledClassesDir.exists()) {
|
||||
compiledClassesDir.walkTopDown()
|
||||
.filter { it.isFile }
|
||||
.forEach { file ->
|
||||
val relativePath = file.relativeTo(compiledClassesDir).path.replace(File.separatorChar, '/')
|
||||
patchedFiles[relativePath] = file.readBytes()
|
||||
}
|
||||
}
|
||||
|
||||
logger.lifecycle("Patching JAR with ${patchedFiles.size} compiled files")
|
||||
|
||||
// Collect all entries: patched files override original
|
||||
val allEntries = mutableMapOf<String, ByteArray?>() // null = directory
|
||||
|
||||
ZipFile(originalJar).use { original ->
|
||||
original.entries().asSequence().forEach { entry ->
|
||||
allEntries[entry.name] = if (entry.isDirectory) null else original.getInputStream(entry).readBytes()
|
||||
}
|
||||
}
|
||||
|
||||
// Override with patched files
|
||||
patchedFiles.forEach { (path, content) ->
|
||||
logger.lifecycle(" Patching: $path")
|
||||
allEntries[path] = content
|
||||
}
|
||||
|
||||
// Write sorted entries with STORED compression and LF normalization
|
||||
patchedJar.outputStream().buffered().let { ZipOutputStream(it) }.use { output ->
|
||||
output.setMethod(ZipOutputStream.STORED)
|
||||
|
||||
allEntries.keys.sorted().forEach { name ->
|
||||
val content = allEntries[name]
|
||||
if (content == null) {
|
||||
// Directory
|
||||
val entry = ZipEntry(name).apply {
|
||||
time = 0
|
||||
size = 0
|
||||
compressedSize = 0
|
||||
crc = 0
|
||||
method = ZipEntry.STORED
|
||||
}
|
||||
output.putNextEntry(entry)
|
||||
output.closeEntry()
|
||||
} else {
|
||||
writeStoredEntry(output, name, content)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.lifecycle("Created patched JAR: $patchedJar")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user