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

154 lines
6.2 KiB

package dev.openrs2.bundler
import com.github.michaelbull.logging.InlineLogger
import com.google.inject.Guice
import dev.openrs2.asm.classpath.ClassPath
import dev.openrs2.asm.classpath.Library
import dev.openrs2.bundler.transform.BufferSizeTransformer
import dev.openrs2.bundler.transform.CachePathTransformer
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.PublicKeyTransformer
import dev.openrs2.bundler.transform.ResourceTransformer
import dev.openrs2.bundler.transform.RightClickTransformer
import dev.openrs2.bundler.transform.TypoTransformer
import dev.openrs2.common.crypto.Pkcs12KeyStore
import java.nio.file.Path
import java.nio.file.Paths
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
fun main() {
val injector = Guice.createInjector(BundlerModule())
val bundler = injector.getInstance(Bundler::class.java)
bundler.run(Paths.get("nonfree/code"), Paths.get("nonfree/code/bundle"), Paths.get("conf/loader.p12"))
}
@Singleton
class Bundler @Inject constructor(publicKeyTransformer: PublicKeyTransformer) {
private val transformers = TRANSFORMERS + publicKeyTransformer
fun run(input: Path, output: Path, keyStorePath: Path) {
// read input jars/packs
logger.info { "Reading input jars" }
val unpacker = Library.readJar(input.resolve("game_unpacker.dat"))
val loader = Library.readJar(input.resolve("loader.jar"))
val glLoader = Library.readJar(input.resolve("loader_gl.jar"))
val gl = Library.readPack(input.resolve("jaggl.pack200"))
val client = Library.readJar(input.resolve("runescape.jar"))
val glClient = Library.readPack(input.resolve("runescape_gl.pack200"))
// bundle libraries together into a common classpath
val runtime = ClassLoader.getSystemClassLoader()
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.compressJar("unpackclass.pack", "game_unpacker.dat", classPath, unpacker)
val clientPack = Resource.compressPack("runescape.pack200", "main_file_cache.dat0", classPath, client)
val clientJs5 = Resource.compressJs5("runescape.js5", "main_file_cache.dat1", classPath, client)
val glClientPack = Resource.compressPack("runescape_gl.pack200", "main_file_cache.dat3", glClassPath, glClient)
val glClientJs5 = Resource.compressJs5("runescape_gl.js5", "main_file_cache.dat4", glClassPath, glClient)
val glPack = Resource.compressPack("jaggl.pack200", "main_file_cache.dat5", glClassPath, gl)
val glJs5 = Resource.compressJs5("jaggl.js5", "main_file_cache.dat6", glClassPath, gl)
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" }
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.writeJar(classPath, output.resolve("runescape.jar"), unsignedManifest)
val keyStore = Pkcs12KeyStore.open(keyStorePath)
loader.writeSignedJar(classPath, output.resolve("loader.jar"), keyStore, signedManifest)
glLoader.writeSignedJar(glClassPath, output.resolve("loader_gl.jar"), keyStore, signedManifest)
}
companion object {
private val logger = InlineLogger()
val TRANSFORMERS = listOf(
BufferSizeTransformer(),
CachePathTransformer(),
HostCheckTransformer(),
MacResizeTransformer(),
RightClickTransformer(),
LoadLibraryTransformer(),
PlatformDetectionTransformer(),
TypoTransformer()
)
private val unsignedManifest = Manifest()
private val signedManifest: Manifest
private val APPLICATION_NAME = Attributes.Name("Application-Name")
private val PERMISSIONS = Attributes.Name("Permissions")
init {
unsignedManifest.mainAttributes[MANIFEST_VERSION] = "1.0"
unsignedManifest.mainAttributes[APPLICATION_NAME] = "OpenRS2"
unsignedManifest.mainAttributes[PERMISSIONS] = "sandbox"
signedManifest = Manifest(unsignedManifest)
signedManifest.mainAttributes[PERMISSIONS] = "all-permissions"
}
}
}