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.
156 lines
6.1 KiB
156 lines
6.1 KiB
package org.openrs2.patcher
|
|
|
|
import com.github.michaelbull.logging.InlineLogger
|
|
import org.openrs2.asm.classpath.ClassPath
|
|
import org.openrs2.asm.classpath.Library
|
|
import org.openrs2.asm.io.JarLibraryReader
|
|
import org.openrs2.asm.io.JarLibraryWriter
|
|
import org.openrs2.asm.io.ManifestJarLibraryWriter
|
|
import org.openrs2.asm.io.Pack200LibraryReader
|
|
import org.openrs2.asm.io.Pack200LibraryWriter
|
|
import org.openrs2.asm.io.PackClassLibraryWriter
|
|
import org.openrs2.asm.io.SignedJarLibraryWriter
|
|
import org.openrs2.asm.transform.Transformer
|
|
import org.openrs2.conf.Config
|
|
import org.openrs2.crypto.Pkcs12KeyStore
|
|
import org.openrs2.patcher.transform.ResourceTransformer
|
|
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
|
|
public class Patcher @Inject constructor(
|
|
@PatcherQualifier private val transformers: Set<Transformer>,
|
|
private val config: Config,
|
|
private val packClassLibraryWriter: PackClassLibraryWriter
|
|
) {
|
|
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"
|
|
}
|
|
|
|
public fun run(input: Path, output: Path, keyStorePath: Path) {
|
|
// read input jars/packs
|
|
logger.info { "Reading input jars" }
|
|
val unpacker = Library.read("unpackclass", input.resolve("unpackclass.pack"), JarLibraryReader)
|
|
val loader = Library.read("loader_sd", input.resolve("loader.jar"), JarLibraryReader)
|
|
val glLoader = Library.read("loader_hd", input.resolve("loader_gl.jar"), JarLibraryReader)
|
|
val gl = Library.read("gl", input.resolve("jaggl.pack200"), Pack200LibraryReader)
|
|
val client = Library.read("client_sd", input.resolve("runescape.jar"), JarLibraryReader)
|
|
val glClient = Library.read("client_hd", 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, packClassLibraryWriter
|
|
)
|
|
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, packClassLibraryWriter
|
|
)
|
|
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, packClassLibraryWriter
|
|
)
|
|
|
|
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")
|
|
}
|
|
}
|
|
|