diff --git a/bundler/src/main/java/dev/openrs2/bundler/Bundler.kt b/bundler/src/main/java/dev/openrs2/bundler/Bundler.kt index 68262dd6..0a8f4308 100644 --- a/bundler/src/main/java/dev/openrs2/bundler/Bundler.kt +++ b/bundler/src/main/java/dev/openrs2/bundler/Bundler.kt @@ -6,6 +6,7 @@ import dev.openrs2.bundler.transform.HostCheckTransformer import dev.openrs2.bundler.transform.LoadLibraryTransformer import dev.openrs2.bundler.transform.MacResizeTransformer import dev.openrs2.bundler.transform.PlatformDetectionTransformer +import dev.openrs2.bundler.transform.ResourceTransformer import dev.openrs2.bundler.transform.RightClickTransformer class Bundler { @@ -17,7 +18,8 @@ class Bundler { MacResizeTransformer(), RightClickTransformer(), LoadLibraryTransformer(), - PlatformDetectionTransformer() + PlatformDetectionTransformer(), + ResourceTransformer() ) } } diff --git a/bundler/src/main/java/dev/openrs2/bundler/Resource.kt b/bundler/src/main/java/dev/openrs2/bundler/Resource.kt new file mode 100644 index 00000000..8233178c --- /dev/null +++ b/bundler/src/main/java/dev/openrs2/bundler/Resource.kt @@ -0,0 +1,96 @@ +package dev.openrs2.bundler + +import java.security.MessageDigest +import java.util.zip.CRC32 +import java.util.zip.Deflater + +class Resource( + val source: String, + val destination: String, + val digest: ByteArray, + val uncompressedSize: Int, + val content: ByteArray +) { + val compressedSize: Int + get() = content.size + + init { + require(digest.size == 20) + } + + companion object { + fun compress(source: String, destination: String, uncompressed: ByteArray): Resource { + val crc = CRC32() + crc.update(uncompressed) + + val sourceWithCrc = source.replace(".", "_${crc.value.toInt()}.") + + val digest = MessageDigest.getInstance("SHA-1") + digest.update(uncompressed) + + val compressed = ByteArray(uncompressed.size) + val compressedSize: Int + val deflater = Deflater(Deflater.BEST_COMPRESSION, true) + try { + deflater.setInput(uncompressed) + deflater.finish() + + compressedSize = deflater.deflate(compressed) + } finally { + deflater.end() + } + + val content = if (compressedSize < uncompressed.size) { + compressed.copyOf(compressedSize) + } else { + uncompressed + } + + return Resource(sourceWithCrc, destination, digest.digest(), uncompressed.size, content) + } + + private fun compress(source: String, destination: String, resource: String): Resource { + val uncompressed = Resource::class.java.getResourceAsStream(resource).use { it.readBytes() } + return compress(source, destination, uncompressed) + } + + fun compressGlResources() = listOf( + // Windows i386 + listOf( + compress("jaggl_0_0.lib", "jaggl.dll", "/natives/windows-i386/jaggl.dll") + ), + + // Windows amd64 + listOf( + compress("jaggl_1_0.lib", "jaggl.dll", "/natives/windows-amd64/jaggl.dll") + ), + + // macOS i386 + listOf( + compress("jaggl_2_0.lib", "libjaggl.dylib", "/natives/mac-i386/libjaggl.dylib") + ), + + // macOS amd64 + listOf( + compress("jaggl_3_0.lib", "libjaggl.dylib", "/natives/mac-amd64/libjaggl.dylib") + ), + + // Linux i386 + listOf( + compress("jaggl_4_0.lib", "libjaggl.so", "/natives/linux-i386/libjaggl.so"), + compress("jaggl_4_1.lib", "libjaggl_dri.so", "/natives/linux-i386/libjaggl_dri.so") + ), + + // Linux amd64 + listOf( + compress("jaggl_5_0.lib", "libjaggl.so", "/natives/linux-amd64/libjaggl.so"), + compress("jaggl_5_1.lib", "libjaggl_dri.so", "/natives/linux-amd64/libjaggl_dri.so") + ) + ) + + fun compressMiscResources() = listOf( + compress("jagmisc_0.lib", "jagmisc.dll", "/natives/windows-i386/jagmisc.dll"), + compress("jagmisc_1.lib", "jagmisc.dll", "/natives/windows-amd64/jagmisc.dll") + ) + } +} diff --git a/bundler/src/main/java/dev/openrs2/bundler/transform/ResourceTransformer.kt b/bundler/src/main/java/dev/openrs2/bundler/transform/ResourceTransformer.kt new file mode 100644 index 00000000..f7f52911 --- /dev/null +++ b/bundler/src/main/java/dev/openrs2/bundler/transform/ResourceTransformer.kt @@ -0,0 +1,10 @@ +package dev.openrs2.bundler.transform + +import dev.openrs2.asm.transform.Transformer +import dev.openrs2.bundler.Resource + +class ResourceTransformer( + private val resources: List? = null, + private val glResources: List> = Resource.compressGlResources(), + private val miscResources: List = Resource.compressMiscResources() +) : Transformer()