Open-source multiplayer game server compatible with the RuneScape client https://www.openrs2.org/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
openrs2/bundler/src/main/java/dev/openrs2/bundler/Bundler.kt

155 lines
6.0 KiB

package dev.openrs2.bundler
import com.github.michaelbull.logging.InlineLogger
import dev.openrs2.asm.classpath.ClassPath
import dev.openrs2.asm.classpath.Library
import dev.openrs2.asm.io.JarLibraryReader
import dev.openrs2.asm.io.JarLibraryWriter
import dev.openrs2.asm.io.Js5LibraryWriter
import dev.openrs2.asm.io.ManifestJarLibraryWriter
import dev.openrs2.asm.io.Pack200LibraryReader
import dev.openrs2.asm.io.Pack200LibraryWriter
import dev.openrs2.asm.io.SignedJarLibraryWriter
import dev.openrs2.asm.transform.Transformer
import dev.openrs2.bundler.transform.ResourceTransformer
import dev.openrs2.conf.Config
import dev.openrs2.crypto.Pkcs12KeyStore
import java.nio.file.Files
import java.nio.file.Path
import java.util.jar.Attributes
import java.util.jar.Attributes.Name.MANIFEST_VERSION
import java.util.jar.Manifest
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class Bundler @Inject constructor(
@BundlerQualifier private val transformers: Set<@JvmSuppressWildcards Transformer>,
private val config: Config
) {
private val unsignedManifest = Manifest().apply {
mainAttributes[MANIFEST_VERSION] = "1.0"
mainAttributes[APPLICATION_NAME] = config.game
mainAttributes[PERMISSIONS] = "sandbox"
}
private val signedManifest = Manifest().apply {
mainAttributes[MANIFEST_VERSION] = "1.0"
mainAttributes[APPLICATION_NAME] = config.game
mainAttributes[PERMISSIONS] = "all-permissions"
}
fun run(input: Path, output: Path, keyStorePath: Path) {
// read input jars/packs
logger.info { "Reading input jars" }
val unpacker = Library.read(input.resolve("unpackclass.pack"), JarLibraryReader)
val loader = Library.read(input.resolve("loader.jar"), JarLibraryReader)
val glLoader = Library.read(input.resolve("loader_gl.jar"), JarLibraryReader)
val gl = Library.read(input.resolve("jaggl.pack200"), Pack200LibraryReader)
val client = Library.read(input.resolve("runescape.jar"), JarLibraryReader)
val glClient = Library.read(input.resolve("runescape_gl.pack200"), Pack200LibraryReader)
// bundle libraries together into a common classpath
val runtime = ClassLoader.getPlatformClassLoader()
val classPath = ClassPath(
runtime,
dependencies = listOf(unpacker),
libraries = listOf(client, loader)
)
val glClassPath = ClassPath(
runtime,
dependencies = listOf(gl, unpacker),
libraries = listOf(glClient, glLoader)
)
// run simple transformers
logger.info { "Transforming client" }
for (transformer in transformers) {
logger.info { "Running transformer ${transformer.javaClass.simpleName}" }
transformer.transform(classPath)
}
logger.info { "Transforming client_gl" }
for (transformer in transformers) {
logger.info { "Running transformer ${transformer.javaClass.simpleName}" }
transformer.transform(glClassPath)
}
// compress resources
logger.info { "Compressing resources" }
val unpackerJar = Resource.compressLibrary(
"unpackclass.pack", "game_unpacker.dat", classPath, unpacker, JarLibraryWriter
)
val clientPack = Resource.compressLibrary(
"runescape.pack200", "main_file_cache.dat0", classPath, client, Pack200LibraryWriter
)
val clientJs5 = Resource.compressLibrary(
"runescape.js5", "main_file_cache.dat1", classPath, client, Js5LibraryWriter
)
val glClientPack = Resource.compressLibrary(
"runescape_gl.pack200", "main_file_cache.dat3", glClassPath, glClient, Pack200LibraryWriter
)
val glClientJs5 = Resource.compressLibrary(
"runescape_gl.js5", "main_file_cache.dat4", glClassPath, glClient, Js5LibraryWriter
)
val glPack = Resource.compressLibrary(
"jaggl.pack200", "main_file_cache.dat5", glClassPath, gl, Pack200LibraryWriter
)
val glJs5 = Resource.compressLibrary(
"jaggl.js5", "main_file_cache.dat6", glClassPath, gl, Js5LibraryWriter
)
val glNatives = Resource.compressGlNatives()
val miscNatives = Resource.compressMiscNatives()
// update checksums in the loader
logger.info { "Updating checksums" }
val resourceTransformer = ResourceTransformer(
resources = listOf(unpackerJar, clientPack, clientJs5),
glResources = glNatives,
miscResources = miscNatives
)
resourceTransformer.transform(classPath)
val glResourceTransformer = ResourceTransformer(
resources = listOf(unpackerJar, glClientPack, glClientJs5, glPack, glJs5),
glResources = glNatives,
miscResources = miscNatives
)
glResourceTransformer.transform(glClassPath)
// write all resources to disk
logger.info { "Writing resources" }
Files.createDirectories(output)
val resources = listOf(
unpackerJar,
clientPack,
clientJs5,
glClientPack,
glClientJs5,
glPack,
glJs5
) + glNatives.flatten() + miscNatives
for (resource in resources) {
resource.write(output)
}
// write unsigned client and loaders
client.write(output.resolve("runescape.jar"), ManifestJarLibraryWriter(unsignedManifest), classPath)
val keyStore = Pkcs12KeyStore.open(keyStorePath, config.game)
loader.write(output.resolve("loader.jar"), SignedJarLibraryWriter(signedManifest, keyStore), classPath)
glLoader.write(output.resolve("loader_gl.jar"), SignedJarLibraryWriter(signedManifest, keyStore), glClassPath)
}
private companion object {
private val logger = InlineLogger()
private val APPLICATION_NAME = Attributes.Name("Application-Name")
private val PERMISSIONS = Attributes.Name("Permissions")
}
}