-
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
6ea5559
commit 723501f
Showing
14 changed files
with
616 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
name: Build Release | ||
on: | ||
release: | ||
types: [ created ] | ||
jobs: | ||
build: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v2 | ||
|
||
- name: Set up JDK 17 | ||
uses: actions/setup-java@v2 | ||
with: | ||
distribution: 'adopt' | ||
java-version: '17' | ||
|
||
- name: Grant execute permission for gradlew | ||
run: chmod +x gradlew | ||
|
||
- name: Publish | ||
run: ./gradlew publish -Pmvn.user=${{ secrets.MAVEN_USER }} -Pmvn.key=${{ secrets.MAVEN_TOKEN }} | ||
|
||
- uses: actions/upload-artifact@v2 | ||
with: | ||
name: PatchBase Artifacts | ||
path: ./build/libs/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
name: Build Snapshot | ||
|
||
on: | ||
push: | ||
branches-ignore: | ||
- 'feature/**' | ||
|
||
jobs: | ||
build: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v2 | ||
|
||
- name: Set up JDK 17 | ||
uses: actions/setup-java@v3 | ||
with: | ||
distribution: 'temurin' | ||
java-version: '17' | ||
cache: 'gradle' | ||
|
||
- name: Grant execute permission for gradlew | ||
run: chmod +x gradlew | ||
|
||
- name: Publish | ||
run: ./gradlew publish -Pversion_snapshot -Pmvn.user=${{ secrets.MAVEN_USER }} -Pmvn.key=${{ secrets.MAVEN_TOKEN }} -x test | ||
|
||
- uses: actions/upload-artifact@v2 | ||
with: | ||
name: PatchBase Snapshot Artifacts | ||
path: ./build/libs/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,113 @@ | ||
import java.net.URI | ||
|
||
plugins { | ||
id("java") | ||
kotlin("jvm") version "1.8.21" | ||
`java-gradle-plugin` | ||
`maven-publish` | ||
} | ||
|
||
version = if (project.hasProperty("version_snapshot")) project.properties["version"] as String + "-SNAPSHOT" else project.properties["version"] as String | ||
group = project.properties["maven_group"] as String | ||
|
||
base { | ||
archivesName.set(project.properties["archives_base_name"] as String) | ||
} | ||
|
||
group = "org.example" | ||
version = "1.0-SNAPSHOT" | ||
val installer by sourceSets.creating | ||
|
||
sourceSets { | ||
main { | ||
compileClasspath += installer.output | ||
runtimeClasspath += installer.output | ||
} | ||
} | ||
|
||
repositories { | ||
maven("https://maven.wagyourtail.xyz/releases") | ||
maven("https://maven.wagyourtail.xyz/snapshots") | ||
maven("https://maven.jemnetworks.com/snapshots") | ||
mavenCentral() | ||
} | ||
|
||
configurations { | ||
implementation { | ||
extendsFrom(configurations.named("installerImplementation").get()) | ||
} | ||
} | ||
|
||
dependencies { | ||
testImplementation(platform("org.junit:junit-bom:5.9.1")) | ||
testImplementation("org.junit.jupiter:junit-jupiter") | ||
testImplementation(kotlin("test")) | ||
|
||
runtimeOnly(gradleApi()) | ||
|
||
implementation("xyz.wagyourtail.unimined:unimined:1.1.0-SNAPSHOT") | ||
"installerImplementation"("io.github.java-diff-utils:java-diff-utils:4.12") | ||
"installerImplementation"("io.github.prcraftmc:class-diff:1.0-SNAPSHOT") | ||
"installerImplementation"("org.jetbrains:annotations:24.0.1") | ||
} | ||
|
||
gradlePlugin { | ||
plugins { | ||
create("xyz.wagyourtail.patchbase") { | ||
id = "xyz.wagyourtail.patchbase" | ||
implementationClass = "xyz.wagyourtail.patchbase.gradle.PatchPlugin" | ||
} | ||
} | ||
} | ||
|
||
gradlePlugin { | ||
plugins { | ||
create("xyz.wagyourtail.patchbase-creator") { | ||
id = "xyz.wagyourtail.patchbase-creator" | ||
implementationClass = "xyz.wagyourtail.patchbase.gradle.PatchCreatorPlugin" | ||
} | ||
} | ||
} | ||
|
||
tasks.jar { | ||
from(sourceSets.main.get().output, installer.output) | ||
} | ||
|
||
project.evaluationDependsOnChildren() | ||
|
||
val installerJar by tasks.registering(Jar::class) { | ||
group = "build" | ||
archiveClassifier.set("installer") | ||
from(installer.output) | ||
} | ||
|
||
tasks.test { | ||
useJUnitPlatform() | ||
} | ||
|
||
tasks.build { | ||
dependsOn(installerJar) | ||
} | ||
|
||
publishing { | ||
repositories { | ||
maven { | ||
name = "WagYourMaven" | ||
url = if (project.hasProperty("version_snapshot")) { | ||
URI.create("https://maven.wagyourtail.xyz/snapshots/") | ||
} else { | ||
URI.create("https://maven.wagyourtail.xyz/releases/") | ||
} | ||
credentials { | ||
username = project.findProperty("mvn.user") as String? ?: System.getenv("USERNAME") | ||
password = project.findProperty("mvn.key") as String? ?: System.getenv("TOKEN") | ||
} | ||
} | ||
} | ||
publications { | ||
create<MavenPublication>("maven") { | ||
groupId = project.group as String | ||
artifactId = project.properties["archives_base_name"] as String? ?: project.name | ||
version = project.version as String | ||
|
||
artifact(installerJar.get()) { | ||
classifier = "installer" | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
kotlin.code.style=official | ||
|
||
org.gradle.jvmargs=-Xmx1G | ||
org.gradle.parallel=true | ||
|
||
maven_group=xyz.wagyourtail.unimined | ||
archives_base_name=patchbase | ||
version=1.0.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
rootProject.name = "ExampleClient" | ||
rootProject.name = "patchbase" | ||
|
||
include("class-diff") |
109 changes: 109 additions & 0 deletions
109
src/installer/java/xyz/wagyourtail/patchbase/installer/PatchbaseInstaller.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
package xyz.wagyourtail.patchbase.installer; | ||
|
||
import io.github.prcraftmc.classdiff.ClassPatcher; | ||
import io.github.prcraftmc.classdiff.format.DiffReader; | ||
import org.objectweb.asm.ClassReader; | ||
import org.objectweb.asm.ClassWriter; | ||
import org.objectweb.asm.tree.ClassNode; | ||
|
||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import java.net.URI; | ||
import java.nio.file.*; | ||
import java.util.Map; | ||
import java.util.function.BiConsumer; | ||
import java.util.function.Function; | ||
import java.util.zip.ZipInputStream; | ||
import java.util.zip.ZipOutputStream; | ||
|
||
public class PatchbaseInstaller { | ||
|
||
/* | ||
* create your installer around this method. | ||
*/ | ||
public void patch(Path patchJar, Path baseJar, Path outputJar) throws IOException { | ||
Files.createDirectories(outputJar.getParent()); | ||
Files.copy(baseJar, outputJar, StandardCopyOption.REPLACE_EXISTING); | ||
try (FileSystem fs = openZipFileSystem(outputJar)) { | ||
forEachInZip(patchJar, (entry, is) -> { | ||
if (entry.endsWith(".cdiff")) { | ||
try { | ||
readZipInputStreamFor(baseJar, entry.substring(0, entry.length() - 6), true, original -> { | ||
try { | ||
ClassWriter cw = new ClassWriter(0); | ||
ClassNode node = new ClassNode(); | ||
new ClassReader(original).accept(node, ClassReader.SKIP_DEBUG); | ||
ClassPatcher.patch(node, new DiffReader(is.readAllBytes())); | ||
node.accept(cw); | ||
Path p = fs.getPath(entry.substring(0, entry.length() - 6)); | ||
if (p.getParent() != null) Files.createDirectories(p.getParent()); | ||
Files.write(p, cw.toByteArray(), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING); | ||
} catch (IOException e) { | ||
throw new RuntimeException(e); | ||
} | ||
return null; | ||
}); | ||
} catch (IOException e) { | ||
throw new RuntimeException(e); | ||
} | ||
} else { | ||
try { | ||
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); | ||
} | ||
} | ||
}); | ||
} | ||
} | ||
|
||
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(); | ||
while (zipEntry != null) { | ||
if (zipEntry.isDirectory()) { | ||
zipEntry = zis.getNextEntry(); | ||
continue; | ||
} | ||
if (zipEntry.getName().equals(entry)) { | ||
return action.apply(zis); | ||
} | ||
zipEntry = zis.getNextEntry(); | ||
} | ||
} | ||
if (throwIfMissing) { | ||
throw new IllegalArgumentException("Missing file " + entry + " in " + path); | ||
} | ||
return null; | ||
} | ||
|
||
public static void forEachInZip(Path path, BiConsumer<String, InputStream> action) throws IOException { | ||
try (ZipInputStream zis = new ZipInputStream(Files.newInputStream(path))) { | ||
var entry = zis.getNextEntry(); | ||
while (entry != null) { | ||
if (entry.isDirectory()) { | ||
entry = zis.getNextEntry(); | ||
continue; | ||
} | ||
action.accept(entry.getName(), zis); | ||
entry = zis.getNextEntry(); | ||
} | ||
} | ||
} | ||
|
||
public static FileSystem openZipFileSystem(Path path) throws IOException { | ||
return openZipFileSystem(path, Map.of()); | ||
} | ||
|
||
public static FileSystem openZipFileSystem(Path path, Map<String, Object> args) throws IOException { | ||
if (!Files.exists(path) && args.getOrDefault("create", false).equals(true)) { | ||
try (ZipOutputStream zos = new ZipOutputStream(Files.newOutputStream(path))) { | ||
zos.closeEntry(); | ||
} | ||
} | ||
return FileSystems.newFileSystem(URI.create("jar:" + path.toUri()), args, null); | ||
} | ||
|
||
} |
35 changes: 35 additions & 0 deletions
35
src/main/kotlin/xyz/wagyourtail/patchbase/gradle/PatchBaseMinecraftTransformer.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package xyz.wagyourtail.patchbase.gradle | ||
|
||
import org.gradle.api.Project | ||
import xyz.wagyourtail.patchbase.installer.PatchbaseInstaller | ||
import xyz.wagyourtail.unimined.api.minecraft.MinecraftConfig | ||
import xyz.wagyourtail.unimined.internal.minecraft.MinecraftProvider | ||
import xyz.wagyourtail.unimined.internal.minecraft.patch.MinecraftJar | ||
import xyz.wagyourtail.unimined.internal.minecraft.patch.jarmod.JarModAgentMinecraftTransformer | ||
import xyz.wagyourtail.unimined.internal.minecraft.patch.jarmod.JarModMinecraftTransformer | ||
import xyz.wagyourtail.unimined.util.withSourceSet | ||
|
||
fun MinecraftConfig.patchBase(action: PatchBaseMinecraftTransformer.() -> Unit = {}) { | ||
customPatcher(PatchBaseMinecraftTransformer(this.project, this as MinecraftProvider), action) | ||
} | ||
|
||
class PatchBaseMinecraftTransformer(project: Project, provider: MinecraftProvider) : JarModAgentMinecraftTransformer(project, provider) { | ||
val patchBase = project.configurations.maybeCreate("patchBase".withSourceSet(provider.sourceSet)) | ||
|
||
override fun transform(minecraft: MinecraftJar): MinecraftJar { | ||
val patchDep = patchBase.dependencies.last() | ||
val patchJar = patchBase.files(patchDep).first { it.extension == "jar" || it.extension == "zip" } | ||
val outputFolder = minecraft.path.parent.resolve(patchDep.name).resolve(patchDep.version) | ||
|
||
val patchedMC = MinecraftJar( | ||
minecraft, | ||
parentPath = outputFolder, | ||
patches = minecraft.patches + "patchbase" | ||
) | ||
|
||
PatchbaseInstaller().patch(patchJar.toPath(), minecraft.path, patchedMC.path) | ||
|
||
return super.transform(patchedMC) | ||
} | ||
|
||
} |
Oops, something went wrong.