Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 16 additions & 5 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
import java.net.URI

plugins {
kotlin("jvm") version "1.9.23"
kotlin("jvm") version "2.1.20"
`java-gradle-plugin`
`maven-publish`
}

version = "${project.properties["version"]}" + if (project.hasProperty("version_snapshot")) "-SNAPSHOT" else ""
group = "${project.properties["maven_group"]}"

java {
toolchain.languageVersion = JavaLanguageVersion.of(8)
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}

kotlin {
jvmToolchain(8)
}

base.archivesName = "${project.properties["archives_base_name"]}"

val main: SourceSet by sourceSets.getting
Expand Down Expand Up @@ -39,7 +49,8 @@ dependencies {

runtimeOnly(gradleApi())

implementation("xyz.wagyourtail.unimined:unimined:1.3.15")
implementation("xyz.wagyourtail.unimined:unimined:1.4.2")
implementation("xyz.wagyourtail.unimined.mapping:unimined-mapping-library-jvm:1.2.1")
installerImplementation("io.github.java-diff-utils:java-diff-utils:4.16")
installerImplementation("net.neoforged.installertools:binarypatcher:3.0.13")
installerImplementation("org.ow2.asm:asm:9.8")
Expand Down Expand Up @@ -109,9 +120,9 @@ publishing {
}
publications {
create<MavenPublication>("maven") {
groupId = project.group as String
artifactId = project.properties["archives_base_name"] as String? ?: project.name
version = project.version as String
groupId = "${project.group}"
artifactId = "${project.properties["archives_base_name"]}"
version = "${project.version}"

artifact(installerJar.get()) {
classifier = "installer"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@
import java.io.InputStream;
import java.net.URI;
import java.nio.file.*;
import java.util.Collections;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

Expand All @@ -27,9 +29,15 @@ public void patch(Path patchJar, Path baseJar, Path outputJar) throws IOExceptio
Files.copy(baseJar, outputJar, StandardCopyOption.REPLACE_EXISTING);
try (FileSystem fs = openZipFileSystem(outputJar)) {
forEachInZip(patchJar, (entry, is) -> {
if (entry.endsWith(".binpatch")) {
try {
readZipInputStreamFor(baseJar, entry.substring(0, entry.length() - 6), true, originalStream -> {
String target = entry.substring(0, entry.length() - 6);
try {
if (entry.endsWith(".deleted") || (entry.endsWith(".binpatch") && is.available() == 0)) {
System.out.println("Deleting " + target);
Path fileToDelete = fs.getPath(target);
Files.deleteIfExists(fileToDelete);
} else if (entry.endsWith(".binpatch")) {
readZipInputStreamFor(baseJar, target, true, originalStream -> {
System.out.println("Patching " + target);
try {
byte[] original = new ClassWriter(new ClassReader(originalStream), ClassReader.SKIP_DEBUG).toByteArray();
byte[] result = patch(original, Patch.from(is));
Expand All @@ -47,25 +55,21 @@ public void patch(Path patchJar, Path baseJar, Path outputJar) throws IOExceptio
}
return null;
});
} catch (IOException e) {
throw new RuntimeException(e);
}
} else {
try {
} else {
Path p = fs.getPath(entry);
if (p.getParent() != null) Files.createDirectories(p.getParent());
Files.copy(is, p, StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
throw new RuntimeException(e);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
});
}
}

public static <T> T readZipInputStreamFor(Path path, String entry, boolean throwIfMissing, Function<InputStream, T> action) throws IOException {
try (ZipInputStream zis = new ZipInputStream(Files.newInputStream(path))) {
var zipEntry = zis.getNextEntry();
ZipEntry zipEntry = zis.getNextEntry();
while (zipEntry != null) {
if (zipEntry.isDirectory()) {
zipEntry = zis.getNextEntry();
Expand All @@ -85,7 +89,7 @@ public static <T> T readZipInputStreamFor(Path path, String entry, boolean throw

public static void forEachInZip(Path path, BiConsumer<String, InputStream> action) throws IOException {
try (ZipInputStream zis = new ZipInputStream(Files.newInputStream(path))) {
var entry = zis.getNextEntry();
ZipEntry entry = zis.getNextEntry();
while (entry != null) {
if (entry.isDirectory()) {
entry = zis.getNextEntry();
Expand All @@ -98,7 +102,7 @@ public static void forEachInZip(Path path, BiConsumer<String, InputStream> actio
}

public static FileSystem openZipFileSystem(Path path) throws IOException {
return openZipFileSystem(path, Map.of());
return openZipFileSystem(path, Collections.emptyMap());
}

public static FileSystem openZipFileSystem(Path path, Map<String, Object> args) throws IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import xyz.wagyourtail.unimined.internal.minecraft.MinecraftProvider
import xyz.wagyourtail.unimined.internal.minecraft.patch.jarmod.JarModAgentMinecraftTransformer
import xyz.wagyourtail.unimined.util.withSourceSet


fun MinecraftConfig.patchBase(action: PatchBaseMinecraftTransformer.() -> Unit = {}) {
customPatcher(PatchBaseMinecraftTransformer(this.project, this as MinecraftProvider), action)
}
Expand All @@ -36,5 +35,4 @@ class PatchBaseMinecraftTransformer(project: Project, provider: MinecraftProvide

return super.transform(patchedMC)
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,13 @@ package xyz.wagyourtail.patchbase.gradle

import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.tasks.SourceSet
import org.gradle.jvm.tasks.Jar
import xyz.wagyourtail.patchbase.gradle.tasks.ApplySourcePatchTask
import xyz.wagyourtail.patchbase.gradle.tasks.CreateClassPatchTask
import xyz.wagyourtail.patchbase.gradle.tasks.CreateSourcePatchTask
import xyz.wagyourtail.unimined.api.minecraft.EnvType
import xyz.wagyourtail.unimined.api.minecraft.MinecraftConfig
import xyz.wagyourtail.unimined.api.unimined
import xyz.wagyourtail.unimined.internal.minecraft.MinecraftProvider
import xyz.wagyourtail.unimined.internal.minecraft.patch.NoTransformMinecraftTransformer
import xyz.wagyourtail.unimined.internal.minecraft.patch.jarmod.JarModAgentMinecraftTransformer
import xyz.wagyourtail.unimined.util.sourceSets
import xyz.wagyourtail.unimined.util.withSourceSet

class PatchCreatorPlugin : Plugin<Project> {

val pluginVersion: String = PatchCreatorPlugin::class.java.`package`.implementationVersion ?: "unknown"


override fun apply(target: Project) {
target.logger.lifecycle("[PatchbaseCreator] Plugin Version: $pluginVersion")

target.extensions.create("patchbase", PatchExtension::class.java)
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@ package xyz.wagyourtail.patchbase.gradle

import org.gradle.api.Project
import org.gradle.api.tasks.SourceSet
import org.gradle.configurationcache.extensions.capitalized
import org.gradle.jvm.tasks.Jar
import org.jetbrains.annotations.ApiStatus
import xyz.wagyourtail.patchbase.gradle.tasks.ApplySourcePatchTask
import xyz.wagyourtail.patchbase.gradle.tasks.CreateClassPatchTask
import xyz.wagyourtail.patchbase.gradle.tasks.CreateSourcePatchTask
import xyz.wagyourtail.unimined.api.minecraft.EnvType
import xyz.wagyourtail.unimined.api.minecraft.MinecraftConfig
import xyz.wagyourtail.unimined.api.unimined
import xyz.wagyourtail.unimined.internal.minecraft.MinecraftProvider
import xyz.wagyourtail.unimined.internal.minecraft.patch.jarmod.JarModAgentMinecraftTransformer
import xyz.wagyourtail.unimined.mapping.EnvType
import xyz.wagyourtail.unimined.util.FinalizeOnRead
import xyz.wagyourtail.unimined.util.capitalized
import xyz.wagyourtail.unimined.util.withSourceSet
import kotlin.io.path.nameWithoutExtension

Expand All @@ -39,7 +39,7 @@ abstract class PatchExtension(val project: Project) {

fun patchBaseCreator(sourceSet: SourceSet, devJar: Boolean = false) {
val mc = project.unimined.minecrafts[sourceSet]!!
if (mc.side == EnvType.COMBINED) {
if (mc.side == EnvType.JOINED) {
project.logger.warn("[PatchBase/Creator ${this.project.path} ${sourceSet}] Merged may make applying patches more difficult, proceed with caution")
}
if (!mc.defaultRemapJar) {
Expand Down Expand Up @@ -91,8 +91,7 @@ abstract class PatchExtension(val project: Project) {
when (mc.side) {
EnvType.CLIENT -> it.classpath.set(project.files(mc.minecraftData.minecraftClientFile))
EnvType.SERVER -> it.classpath.set(project.files(mc.minecraftData.minecraftServerFile))
EnvType.COMBINED -> it.classpath.set(project.files(mc.mergedOfficialMinecraftFile))
else -> throw IllegalStateException("Unknown side: ${mc.side}")
EnvType.JOINED -> it.classpath.set(project.files(mc.mergedOfficialMinecraftFile))
}

it.archiveClassifier.set("patch")
Expand All @@ -118,4 +117,4 @@ abstract class PatchExtension(val project: Project) {
fun patchBase(minecraftConfig: MinecraftConfig) {
minecraftConfig.patchBase()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,11 @@ import org.gradle.api.Plugin
import org.gradle.api.Project

class PatchPlugin : Plugin<Project> {

val pluginVersion: String = PatchPlugin::class.java.`package`.implementationVersion ?: "unknown"


override fun apply(target: Project) {
target.logger.lifecycle("[Patchbase] Plugin Version: $pluginVersion")

target.extensions.create("patchbase", PatchExtension::class.java)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ abstract class AbstractSourceTask : ConventionTask() {
sourcePath.readZipInputStreamFor(path.toString(), true) {
action(it)
}
} catch (e: IllegalArgumentException) {
} catch (_: IllegalArgumentException) {
action(null)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import java.io.File
import kotlin.io.path.*

abstract class ApplySourcePatchTask : AbstractSourceTask() {

@get:Input
abstract val patchDir: Property<File>

Expand Down Expand Up @@ -41,4 +40,4 @@ abstract class ApplySourcePatchTask : AbstractSourceTask() {
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,14 @@ import org.objectweb.asm.ClassWriter
import xyz.wagyourtail.unimined.util.forEachInZip
import xyz.wagyourtail.unimined.util.readZipInputStreamFor
import java.io.InputStream
import java.nio.file.Path
import kotlin.io.path.*

abstract class CreateClassPatchTask : Jar() {
companion object {
val EMPTY_DATA: ByteArray = ByteArray(0)
}

/**
* Shrinks the created `.class` patches by remapping constant pool indices.
*/
Expand All @@ -34,24 +39,32 @@ abstract class CreateClassPatchTask : Jar() {
val tempDir = temporaryDir.resolve("diffs").toPath()
tempDir.deleteRecursively()

inputFile.get().asFile.toPath().forEachInZip { name, stream ->
if (name.endsWith(".class")) {
inputFile.get().asFile.toPath().forEachInZip { name, input ->
fun create(s: String, bytes: ByteArray? = null): Path = tempDir.resolve(s).apply {
parent.createDirectories()
outputStream().use { output ->
if (bytes != null) bytes.let { output.write(it) }
else input.copyTo(output)
}
}

if (name.endsWith(".deleted")) {
val target = name.substringBefore(".deleted")
findClass(target) { original ->
if (original != null) project.logger.info("$target will be deleted.")
else project.logger.warn("$target does not exist in target.")

// Intentionally write empty data, installer will treat this as a deleted file.
create("$name.deleted", EMPTY_DATA)
}
} else if (name.endsWith(".class")) {
// find in classpath
findClass(name) { original ->
if (original != null) {
val target = tempDir.resolve("$name.binpatch")
target.parent.createDirectories()
target.writeBytes(makePatch(original, stream, name))
} else {
val target = tempDir.resolve(name)
target.parent.createDirectories()
target.outputStream().use { stream.copyTo(it) }
}
if (original != null) create("$name.binpatch", makePatch(original, input, name))
else create(name)
}
} else {
val target = tempDir.resolve(name)
target.parent.createDirectories()
target.outputStream().use { stream.copyTo(it) }
create(name)
}
}
from(tempDir)
Expand Down Expand Up @@ -80,11 +93,10 @@ abstract class CreateClassPatchTask : Jar() {
sourcePath.readZipInputStreamFor(name, true) {
action(it)
}
} catch (e: IllegalArgumentException) {
} catch (_: IllegalArgumentException) {
action(null)
}
}
}
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import java.io.File
import kotlin.io.path.*

abstract class CreateSourcePatchTask : AbstractSourceTask() {

@get:Input
abstract val sourceDir: Property<File>

Expand All @@ -21,26 +20,24 @@ abstract class CreateSourcePatchTask : AbstractSourceTask() {

val source = sourceDir.get().toPath()
for (path in source.walk()) {
if (path.extension != "java") {
throw IllegalArgumentException("sourceDir must only contain java files")
}
val relative = path.relativeTo(source)
val targetParent = relative.parent?.let {
output.resolve(it).createDirectories()
} ?: output
findSource(relative) { original ->
if (original != null) {
project.logger.info("Creating a patch for $path")
val target = targetParent.resolve(relative.nameWithoutExtension + ".${relative.extension}.patch")
val diff = diff(relative.name, original.readBytes().decodeToString(), relative.name, path.readText())
if (!diff.trim().isEmpty()) {
target.writeText(diff)
}
} else {
val target = targetParent.resolve(relative.name)
project.logger.info("Copying $path to $target")
path.copyTo(target, overwrite = true)
}
}
}
}

}