diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 7b80106..c30b12b 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -15,7 +15,7 @@ jobs:
- uses: actions/setup-java@v5
with:
distribution: 'temurin'
- java-version: 17
+ java-version: 21
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v5
- name: Build with Gradle
diff --git a/.github/workflows/deploy-snapshot.yml b/.github/workflows/deploy-snapshot.yml
index c630235..5908764 100644
--- a/.github/workflows/deploy-snapshot.yml
+++ b/.github/workflows/deploy-snapshot.yml
@@ -1,7 +1,7 @@
name: Deploy Snapshot
on:
push:
- branches: ['main']
+ branches: ['main', 'dev/v2']
paths-ignore:
- '.idea/**'
- 'license.txt'
@@ -19,7 +19,7 @@ jobs:
- uses: actions/setup-java@v5
with:
distribution: 'temurin'
- java-version: 17
+ java-version: 21
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v5
- name: Get project version
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index a173433..5dc72ab 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -12,7 +12,7 @@ jobs:
- uses: actions/setup-java@v5
with:
distribution: 'temurin'
- java-version: 17
+ java-version: 21
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v5
- name: Deploy
diff --git a/.gitignore b/.gitignore
index 7914dd9..7339233 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,10 +7,7 @@ build/
### IntelliJ IDEA ###
.idea/**
# Need to first allow the directory
-!.idea/inspectionProfiles/
# Then the specific file
-!.idea/inspectionProfiles/Project_Default.xml
-!.idea/misc.xml
*.iws
*.iml
*.ipr
@@ -45,3 +42,4 @@ bin/
.DS_Store
run/
+.kotlin/
diff --git a/.idea/misc.xml b/.idea/misc.xml
deleted file mode 100644
index f54a461..0000000
--- a/.idea/misc.xml
+++ /dev/null
@@ -1,63 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/codebook-cli/src/main/java/io/papermc/codebook/cli/Main.java b/codebook-cli/src/main/java/io/papermc/codebook/cli/Main.java
index a3d9b2d..5e01ff0 100644
--- a/codebook-cli/src/main/java/io/papermc/codebook/cli/Main.java
+++ b/codebook-cli/src/main/java/io/papermc/codebook/cli/Main.java
@@ -96,81 +96,6 @@ static final class SelectedReports {
}
}
- @CommandLine.ArgGroup(
- multiplicity = "1",
- heading = "%n%nThe remapper must be an executable tiny-remapper jar. "
- + "This is the 'fat' classifier when downloading from Maven. It can be provided several different ways, the simplest being to just "
- + "specify the Maven coordinates (with no classifier).%n")
- private RemapperOptions remapper;
-
- static final class RemapperOptions {
- @CommandLine.Option(
- names = {"-r", "--remapper-coords"},
- paramLabel = "",
- description =
- "The Maven coordinates for the executable AutoRenamingTool jar to use for the remapping process.")
- private @Nullable String remapperCoords;
-
- @CommandLine.Option(
- names = {"--remapper-file"},
- paramLabel = "",
- description = "The executable AutoRenamingTool jar to use for the remapping process.")
- private @Nullable Path remapperFile;
-
- @CommandLine.Option(
- names = "--remapper-uri",
- paramLabel = "",
- description =
- "A download URL for the executable AutoRenamingTool jar to use for the remapping process.")
- private @Nullable URI remapperUri;
- }
-
- @CommandLine.ArgGroup(
- heading =
- "%n%nMappings are required when not using the --mc-version option to automatically download a version. "
- + "They can still be optionally provided using one of the 2 mappings options below, "
- + "but one of either --mappings-file or --mappings-uri is required when using --input to manually specify a jar file.%n")
- private @Nullable MappingsOptions mappings;
-
- static final class MappingsOptions {
- @CommandLine.Option(
- names = {"-m", "--mappings-file"},
- paramLabel = "",
- description = "The ProGuard mojmap mappings to use for base remapping.")
- private @Nullable Path mappingsFile;
-
- @CommandLine.Option(
- names = "--mappings-uri",
- paramLabel = "",
- description = "A download URL for the ProGuard mojmap mappings to use for base remapping.")
- private @Nullable URI mappingsUri;
- }
-
- @CommandLine.ArgGroup(
- heading = "%n%nParameter mappings are always optional, and can be specified several different ways.%n")
- private @Nullable ParamMappingsOptions paramMappings;
-
- static final class ParamMappingsOptions {
- @CommandLine.Option(
- names = {"-p", "--params-coords"},
- paramLabel = "",
- description =
- "The Maven coordinates for TinyV2 mappings to use for parameter remapping. This is the preferred option, as it allows omitting other details.")
- private @Nullable String paramsCoords;
-
- @CommandLine.Option(
- names = {"--params-file"},
- paramLabel = "",
- description = "The TinyV2 mappings to use for parameter remapping.")
- private @Nullable Path paramsFile;
-
- @CommandLine.Option(
- names = "--params-uri",
- paramLabel = "",
- description = "A download URL for the TinyV2 mappings to use for parameter remapping.")
- private @Nullable URI paramsUri;
- }
-
@CommandLine.ArgGroup(exclusive = false)
private @Nullable UnpickOptions unpick;
@@ -348,10 +273,6 @@ public Integer call() {
}
private CodeBookContext createContext() {
- if (this.remapper.remapperFile != null) {
- this.verifyJarFile("Remapper", this.remapper.remapperFile);
- }
-
if (this.inputs.inputFile != null) {
this.verifyJarFile("Input", this.inputs.inputFile.inputJar);
@@ -362,18 +283,6 @@ private CodeBookContext createContext() {
}
}
- if (this.mappings == null && this.inputs.mcVersion == null) {
- throw new UserErrorException("No base mappings file was provided, and no MC version was provided. "
- + "When not specifying an MC version, the base mappings file must be manually specified.");
- }
- if (this.mappings != null && this.mappings.mappingsFile != null) {
- this.verifyFileExists("Mappings file", this.mappings.mappingsFile);
- }
-
- if (this.paramMappings != null && this.paramMappings.paramsFile != null) {
- this.verifyFileExists("Param mappings file", this.paramMappings.paramsFile);
- }
-
if (Files.isRegularFile(this.outputJar) && !this.forceWrite) {
throw new UserErrorException(
"Output jar file exists, will not overwrite because --force option was not provided: "
@@ -390,26 +299,6 @@ private CodeBookContext createContext() {
input = new CodeBookJarInput(this.inputs.inputFile.inputJar, classpath);
}
- final @Nullable CodeBookResource remapper = this.getResource(
- "AutoRenamingTool.jar",
- this.remapper,
- r -> r.remapperFile,
- r -> r.remapperUri,
- r -> new Coords(r.remapperCoords, "all", null, this.remapperMavenBaseUrl));
- if (remapper == null) {
- throw new UserErrorException("No remapper provided");
- }
-
- final @Nullable CodeBookResource mappings =
- this.getResource("server_mappings.txt", this.mappings, m -> m.mappingsFile, m -> m.mappingsUri, null);
-
- final @Nullable CodeBookResource paramMappings = this.getResource(
- "parchment.zip",
- this.paramMappings,
- p -> p.paramsFile,
- p -> p.paramsUri,
- p -> new Coords(p.paramsCoords, null, "zip", this.paramsMavenBaseUrl));
-
final @Nullable CodeBookResource unpickDefinitions = this.getResource(
"definitions.unpick",
this.unpick != null ? this.unpick.unpickDefinitions : null,
@@ -442,9 +331,6 @@ private CodeBookContext createContext() {
return CodeBookContext.builder()
.tempDir(this.tempDir)
- .remapperJar(remapper)
- .mappings(mappings)
- .paramMappings(paramMappings)
.unpickDefinitions(unpickDefinitions)
.outputJar(this.outputJar)
.overwrite(this.forceWrite)
diff --git a/gradle.properties b/gradle.properties
index 172bdc1..54e1971 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,2 +1,2 @@
group = io.papermc.codebook
-version = 1.0.19-SNAPSHOT
+version = 2.0.0-SNAPSHOT
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
index 8bdaf60..d997cfc 100644
Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 2e11132..dbc3ce4 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.0-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
diff --git a/gradlew b/gradlew
index adff685..0262dcb 100755
--- a/gradlew
+++ b/gradlew
@@ -57,7 +57,7 @@
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
-# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# https://github.com/gradle/gradle/blob/b631911858264c0b6e4d6603d677ff5218766cee/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
diff --git a/readme.md b/readme.md
index 9b02d85..bc901c9 100644
--- a/readme.md
+++ b/readme.md
@@ -96,7 +96,7 @@ There are 2 methods of providing inputs, and they are mutually exclusive:
Building
========
-Java 17 is required.
+Java 21 is required.
```sh
./gradlew build
diff --git a/src/main/java/io/papermc/codebook/CodeBook.java b/src/main/java/io/papermc/codebook/CodeBook.java
index 49b3973..b2435e9 100644
--- a/src/main/java/io/papermc/codebook/CodeBook.java
+++ b/src/main/java/io/papermc/codebook/CodeBook.java
@@ -30,18 +30,15 @@
import dev.denwav.hypo.asm.AsmOutputWriter;
import dev.denwav.hypo.core.HypoConfig;
import dev.denwav.hypo.core.HypoContext;
-import io.papermc.codebook.config.CodeBookClasspathResource;
import io.papermc.codebook.config.CodeBookContext;
import io.papermc.codebook.config.CodeBookJarInput;
-import io.papermc.codebook.config.CodeBookResource;
import io.papermc.codebook.exceptions.UnexpectedException;
import io.papermc.codebook.exceptions.UserErrorException;
import io.papermc.codebook.pages.CodeBookPage;
import io.papermc.codebook.pages.ExtractVanillaJarPage;
import io.papermc.codebook.pages.FixJarPage;
import io.papermc.codebook.pages.InspectJarPage;
-import io.papermc.codebook.pages.RemapJarPage;
-import io.papermc.codebook.pages.RemapLvtPage;
+import io.papermc.codebook.pages.StripSignaturesPage;
import io.papermc.codebook.pages.UnpickPage;
import io.papermc.codebook.report.Reports;
import io.papermc.codebook.util.IOUtil;
@@ -75,14 +72,14 @@ public void exec() {
private void exec(final Path tempDir) {
this.deleteOutputFile();
+ IOUtil.createDirectories(tempDir);
final var book = List.of(
ExtractVanillaJarPage.class,
- RemapJarPage.class,
+ StripSignaturesPage.class,
InspectJarPage.class,
UnpickPage.class,
- FixJarPage.class,
- RemapLvtPage.class);
+ FixJarPage.class);
Module module = this.createInitialModule(tempDir);
for (final var page : book) {
@@ -113,11 +110,6 @@ private static Injector injector(final Module module) {
}
private Module createInitialModule(final Path tempDir) {
- final @Nullable CodeBookResource mappings = this.ctx.input().resolveMappings(this.ctx, tempDir);
- if (mappings == null) {
- throw new IllegalStateException("No mappings file could be determined for the given configuration");
- }
-
final Path inputJar = this.ctx.input().resolveInputFile(tempDir);
final @Nullable List classpathJars;
if (this.ctx.input() instanceof final CodeBookJarInput input) {
@@ -126,30 +118,9 @@ private Module createInitialModule(final Path tempDir) {
classpathJars = null;
}
- final Path mappingsFile = mappings.resolveResourceFile(tempDir);
- final @Nullable Path paramMappingsFile;
- if (this.ctx.paramMappings() != null) {
- paramMappingsFile = this.ctx.paramMappings().resolveResourceFile(tempDir);
- } else {
- paramMappingsFile = null;
- }
-
- final List remapperJars;
- if (this.ctx.remapperJar() instanceof final CodeBookResource resource) {
- remapperJars = List.of(resource.resolveResourceFile(tempDir));
- } else if (this.ctx.remapperJar() instanceof final CodeBookClasspathResource resource) {
- remapperJars = resource.jars();
- } else {
- throw new LinkageError();
- }
-
final @Nullable Path unpickDefinitions;
if (this.ctx.unpickDefinitions() != null) {
- if (this.ctx.unpickDefinitions().equals(this.ctx.paramMappings())) {
- unpickDefinitions = paramMappingsFile;
- } else {
- unpickDefinitions = this.ctx.unpickDefinitions().resolveResourceFile(tempDir);
- }
+ unpickDefinitions = this.ctx.unpickDefinitions().resolveResourceFile(tempDir);
} else {
unpickDefinitions = null;
}
@@ -165,9 +136,6 @@ protected void configure() {
this.bind(CodeBookPage.ClasspathJars.KEY).toProvider(Providers.of(null));
}
this.bind(CodeBookPage.TempDir.KEY).toInstance(tempDir);
- this.bind(CodeBookPage.MojangMappings.PATH_KEY).toInstance(mappingsFile);
- this.bind(CodeBookPage.ParamMappings.PATH_KEY).toProvider(Providers.of(paramMappingsFile));
- this.bind(CodeBookPage.RemapperJar.KEY).toInstance(remapperJars);
if (unpickDefinitions != null) {
this.bind(CodeBookPage.UnpickDefinitions.KEY).toInstance(unpickDefinitions);
diff --git a/src/main/java/io/papermc/codebook/config/CodeBookContext.java b/src/main/java/io/papermc/codebook/config/CodeBookContext.java
index cd2a2cf..519a509 100644
--- a/src/main/java/io/papermc/codebook/config/CodeBookContext.java
+++ b/src/main/java/io/papermc/codebook/config/CodeBookContext.java
@@ -35,9 +35,6 @@
@RecordBuilder.Options(interpretNotNulls = true)
public record CodeBookContext(
@Nullable @org.jetbrains.annotations.Nullable Path tempDir,
- @NotNull CodeBookRemapper remapperJar,
- @Nullable @org.jetbrains.annotations.Nullable CodeBookResource mappings,
- @Nullable @org.jetbrains.annotations.Nullable CodeBookResource paramMappings,
@Nullable @org.jetbrains.annotations.Nullable CodeBookResource unpickDefinitions,
@NotNull Path outputJar,
boolean overwrite,
diff --git a/src/main/java/io/papermc/codebook/config/CodeBookInput.java b/src/main/java/io/papermc/codebook/config/CodeBookInput.java
index 065a85a..83d01e1 100644
--- a/src/main/java/io/papermc/codebook/config/CodeBookInput.java
+++ b/src/main/java/io/papermc/codebook/config/CodeBookInput.java
@@ -23,7 +23,6 @@
package io.papermc.codebook.config;
import java.nio.file.Path;
-import org.checkerframework.checker.nullness.qual.Nullable;
public sealed interface CodeBookInput permits CodeBookVersionInput, CodeBookJarInput {
@@ -36,13 +35,4 @@ static CodeBookJarInputBuilder ofJar() {
}
Path resolveInputFile(final Path tempDir);
-
- // It's a bit odd for mappings to be here, but the MC version input can specify its own mappings
- default @Nullable CodeBookResource resolveMappings(final CodeBookContext ctx, final Path tempDir) {
- if (ctx.mappings() != null) {
- return ctx.mappings();
- }
-
- return null;
- }
}
diff --git a/src/main/java/io/papermc/codebook/config/CodeBookVersionInput.java b/src/main/java/io/papermc/codebook/config/CodeBookVersionInput.java
index fbdc561..fd0b210 100644
--- a/src/main/java/io/papermc/codebook/config/CodeBookVersionInput.java
+++ b/src/main/java/io/papermc/codebook/config/CodeBookVersionInput.java
@@ -23,11 +23,9 @@
package io.papermc.codebook.config;
import io.papermc.codebook.mojangapi.MinecraftManifest;
-import io.papermc.codebook.mojangapi.MinecraftVersionDownload;
import io.papermc.codebook.mojangapi.MinecraftVersionManifest;
import io.papermc.codebook.util.Downloader;
import java.nio.file.Path;
-import org.checkerframework.checker.nullness.qual.Nullable;
public record CodeBookVersionInput(String mcVersion) implements CodeBookInput {
@@ -44,18 +42,4 @@ public Path resolveInputFile(final Path tempDir) {
Downloader.downloadFile(versionManifest.serverDownload(), targetJar);
return targetJar;
}
-
- @Override
- public CodeBookResource resolveMappings(final CodeBookContext ctx, final Path tempDir) {
- final @Nullable CodeBookResource mappings = CodeBookInput.super.resolveMappings(ctx, tempDir);
- if (mappings != null) {
- return mappings;
- }
-
- final var manifest = MinecraftManifest.getManifest();
- final var versionManifest = MinecraftVersionManifest.getManifestForVersion(manifest, this.mcVersion);
-
- final MinecraftVersionDownload mappingsDownload = versionManifest.serverMappingsDownload();
- return new CodeBookUriResource("server_mappings.txt", mappingsDownload.uri(), mappingsDownload.sha1());
- }
}
diff --git a/src/main/java/io/papermc/codebook/pages/CodeBookPage.java b/src/main/java/io/papermc/codebook/pages/CodeBookPage.java
index ffbe452..23a5988 100644
--- a/src/main/java/io/papermc/codebook/pages/CodeBookPage.java
+++ b/src/main/java/io/papermc/codebook/pages/CodeBookPage.java
@@ -41,7 +41,6 @@
import java.nio.file.Path;
import java.util.IdentityHashMap;
import java.util.List;
-import org.cadixdev.lorenz.MappingSet;
import org.checkerframework.checker.nullness.qual.Nullable;
public abstract class CodeBookPage {
@@ -95,13 +94,6 @@ public void to(final @Nullable T value) {
Key KEY = Key.get(CodeBookContext.class, Context.class);
}
- @Qualifier
- @Target(ElementType.PARAMETER)
- @Retention(RetentionPolicy.RUNTIME)
- public @interface RemapperJar {
- Key> KEY = Key.get(new TypeLiteral<>() {}, RemapperJar.class);
- }
-
@Qualifier
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@@ -116,21 +108,6 @@ public void to(final @Nullable T value) {
Key> KEY = Key.get(new TypeLiteral<>() {}, ClasspathJars.class);
}
- @Qualifier
- @Target(ElementType.PARAMETER)
- @Retention(RetentionPolicy.RUNTIME)
- public @interface MojangMappings {
- Key PATH_KEY = Key.get(Path.class, MojangMappings.class);
- }
-
- @Qualifier
- @Target(ElementType.PARAMETER)
- @Retention(RetentionPolicy.RUNTIME)
- public @interface ParamMappings {
- Key PATH_KEY = Key.get(Path.class, ParamMappings.class);
- Key KEY = Key.get(MappingSet.class, ParamMappings.class);
- }
-
@Qualifier
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
diff --git a/src/main/java/io/papermc/codebook/pages/FixJarPage.java b/src/main/java/io/papermc/codebook/pages/FixJarPage.java
index 0c40b50..6b84e2a 100644
--- a/src/main/java/io/papermc/codebook/pages/FixJarPage.java
+++ b/src/main/java/io/papermc/codebook/pages/FixJarPage.java
@@ -24,13 +24,9 @@
import com.google.common.collect.Iterables;
import dev.denwav.hypo.asm.AsmClassData;
-import dev.denwav.hypo.asm.AsmFieldData;
import dev.denwav.hypo.asm.AsmMethodData;
import dev.denwav.hypo.core.HypoContext;
import dev.denwav.hypo.hydrate.generic.HypoHydration;
-import dev.denwav.hypo.model.data.ClassData;
-import dev.denwav.hypo.model.data.ClassKind;
-import dev.denwav.hypo.model.data.FieldData;
import dev.denwav.hypo.model.data.MethodData;
import dev.denwav.hypo.model.data.Visibility;
import jakarta.inject.Inject;
@@ -41,7 +37,6 @@
import org.checkerframework.checker.nullness.qual.Nullable;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.AnnotationNode;
-import org.objectweb.asm.tree.FieldNode;
import org.objectweb.asm.tree.MethodNode;
public final class FixJarPage extends AsmProcessorPage {
@@ -54,8 +49,6 @@ public FixJarPage(@Hypo final HypoContext context) {
@Override
protected void processClass(final AsmClassData classData) throws IOException {
OverrideAnnotationAdder.addAnnotations(classData);
- EmptyRecordFixer.fixClass(classData);
- RecordFieldAccessFixer.fixClass(classData);
DeprecatedAnnotationAdder.addAnnotations(classData);
}
@@ -123,46 +116,6 @@ private static void addAnnotations(final AsmClassData classData) {
}
}
- private static final class EmptyRecordFixer {
-
- private EmptyRecordFixer() {}
-
- private static void fixClass(final AsmClassData classData) throws IOException {
- if (classData.is(ClassKind.RECORD)) {
- return;
- }
-
- final @Nullable ClassData superClass = classData.superClass();
- if (superClass == null) {
- return;
- }
-
- if (superClass.name().equals("java/lang/Record")) {
- // extends record, but is not marked as such
- classData.getNode().access |= Opcodes.ACC_RECORD;
- }
- }
- }
-
- private static final class RecordFieldAccessFixer {
- private static final int RESET_ACCESS = ~(Opcodes.ACC_PUBLIC | Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED);
-
- private RecordFieldAccessFixer() {}
-
- private static void fixClass(final AsmClassData classData) {
- if (classData.isNot(ClassKind.RECORD)) {
- return;
- }
-
- for (final FieldData field : classData.fields()) {
- if (!field.isStatic() && field.visibility() != Visibility.PRIVATE && field.isFinal()) {
- final FieldNode node = ((AsmFieldData) field).getNode();
- node.access = (node.access & RESET_ACCESS) | Opcodes.ACC_PRIVATE;
- }
- }
- }
- }
-
private static List appendToList(final @Nullable List list, final T value) {
if (list != null) {
list.add(value);
diff --git a/src/main/java/io/papermc/codebook/pages/InspectJarPage.java b/src/main/java/io/papermc/codebook/pages/InspectJarPage.java
index 328ccb9..e265bfd 100644
--- a/src/main/java/io/papermc/codebook/pages/InspectJarPage.java
+++ b/src/main/java/io/papermc/codebook/pages/InspectJarPage.java
@@ -26,8 +26,6 @@
import static dev.denwav.hypo.model.ClassProviderRoot.fromJars;
import static dev.denwav.hypo.model.ClassProviderRoot.ofJdk;
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
import dev.denwav.hypo.asm.AsmClassDataProvider;
import dev.denwav.hypo.asm.hydrate.BridgeMethodHydrator;
import dev.denwav.hypo.asm.hydrate.LambdaCallHydrator;
@@ -36,47 +34,26 @@
import dev.denwav.hypo.core.HypoConfig;
import dev.denwav.hypo.core.HypoContext;
import dev.denwav.hypo.hydrate.HydrationManager;
-import dev.denwav.hypo.mappings.ChangeChain;
-import dev.denwav.hypo.mappings.MappingsCompletionManager;
-import dev.denwav.hypo.mappings.contributors.CopyLambdaParametersDown;
-import dev.denwav.hypo.mappings.contributors.CopyMappingsDown;
-import dev.denwav.hypo.mappings.contributors.CopyRecordParameters;
import io.papermc.codebook.exceptions.UnexpectedException;
import jakarta.inject.Inject;
-import java.io.BufferedReader;
import java.io.IOException;
-import java.nio.file.FileSystem;
-import java.nio.file.FileSystems;
-import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
-import org.cadixdev.bombe.type.signature.FieldSignature;
import org.cadixdev.lorenz.MappingSet;
-import org.cadixdev.lorenz.model.ClassMapping;
-import org.cadixdev.lorenz.model.MethodMapping;
-import org.checkerframework.checker.nullness.qual.Nullable;
-import org.parchmentmc.feather.io.gson.MDCGsonAdapterFactory;
-import org.parchmentmc.feather.io.gson.SimpleVersionAdapter;
-import org.parchmentmc.feather.mapping.MappingDataContainer;
-import org.parchmentmc.feather.mapping.VersionedMappingDataContainer;
-import org.parchmentmc.feather.util.SimpleVersion;
public final class InspectJarPage extends CodeBookPage {
private final Path inputJar;
private final List classpathJars;
- private final @Nullable Path paramMappings;
private final HypoConfig config;
@Inject
public InspectJarPage(
@InputJar final Path inputJar,
@ClasspathJars final List classpathJars,
- @ParamMappings @Nullable final Path paramMappings,
@Hypo final HypoConfig config) {
this.inputJar = inputJar;
this.classpathJars = classpathJars;
- this.paramMappings = paramMappings;
this.config = config;
}
@@ -109,59 +86,9 @@ public void exec() {
} catch (final IOException e) {
throw new UnexpectedException("Failed to hydrate data model", e);
}
-
- if (this.paramMappings != null) {
- // Fill in any missing mapping information
- final MappingSet completedMappings = ChangeChain.create()
- .addLink(
- CopyMappingsDown.createWithoutOverwrite(),
- CopyLambdaParametersDown.createWithoutOverwrite(),
- CopyRecordParameters.create())
- .applyChain(lorenzMappings, MappingsCompletionManager.create(ctx));
-
- this.bind(ParamMappings.KEY).to(completedMappings);
- } else {
- this.bind(ParamMappings.KEY).to(null);
- }
}
private MappingSet loadMappings() {
- if (this.paramMappings == null) {
- return MappingSet.create();
- }
-
- final Gson gson = new GsonBuilder()
- .registerTypeAdapterFactory(new MDCGsonAdapterFactory())
- .registerTypeAdapter(SimpleVersion.class, new SimpleVersionAdapter())
- .create();
-
- try (final FileSystem fs = FileSystems.newFileSystem(this.paramMappings)) {
- final Path jsonFile = fs.getPath("/parchment.json");
- try (final BufferedReader reader = Files.newBufferedReader(jsonFile)) {
- return this.toLorenz(gson.fromJson(reader, VersionedMappingDataContainer.class));
- }
- } catch (final IOException e) {
- throw new UnexpectedException("Failed to read param mappings file", e);
- }
- }
-
- private MappingSet toLorenz(final MappingDataContainer container) {
- final MappingSet mappings = MappingSet.create();
-
- for (final MappingDataContainer.ClassData aClass : container.getClasses()) {
- final ClassMapping, ?> classMapping = mappings.getOrCreateClassMapping(aClass.getName());
- for (final MappingDataContainer.MethodData method : aClass.getMethods()) {
- final MethodMapping methodMapping =
- classMapping.getOrCreateMethodMapping(method.getName(), method.getDescriptor());
- for (final MappingDataContainer.ParameterData param : method.getParameters()) {
- methodMapping.getOrCreateParameterMapping(param.getIndex()).setDeobfuscatedName(param.getName());
- }
- }
- for (final MappingDataContainer.FieldData field : aClass.getFields()) {
- classMapping.getOrCreateFieldMapping(FieldSignature.of(field.getName(), field.getDescriptor()));
- }
- }
-
- return mappings;
+ return MappingSet.create();
}
}
diff --git a/src/main/java/io/papermc/codebook/pages/RemapJarPage.java b/src/main/java/io/papermc/codebook/pages/RemapJarPage.java
deleted file mode 100644
index 902677f..0000000
--- a/src/main/java/io/papermc/codebook/pages/RemapJarPage.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * codebook is a remapper utility for the PaperMC project.
- *
- * Copyright (c) 2023 Kyle Wood (DenWav)
- * Contributors
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 3 only, no later versions.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
- * USA
- */
-
-package io.papermc.codebook.pages;
-
-import io.papermc.codebook.util.IOUtil;
-import io.papermc.codebook.util.JarRunner;
-import jakarta.inject.Inject;
-import java.nio.file.Path;
-import java.util.List;
-
-public final class RemapJarPage extends CodeBookPage {
-
- private final List remapper;
-
- private final Path inputJar;
- private final List classpath;
- private final Path tempDir;
- private final Path mojangMappings;
-
- @Inject
- public RemapJarPage(
- @RemapperJar final List remapper,
- @InputJar final Path inputJar,
- @ClasspathJars final List classpath,
- @TempDir final Path tempDir,
- @MojangMappings final Path mojangMappings) {
- this.remapper = remapper;
- this.inputJar = inputJar;
- this.classpath = classpath;
- this.tempDir = tempDir;
- this.mojangMappings = mojangMappings;
- }
-
- @Override
- public void exec() {
- final Path remapped = this.tempDir.resolve("remapped.jar");
-
- JarRunner.of("AutoRenamingTool", this.remapper)
- .withArgs(
- "--input=" + IOUtil.absolutePathString(this.inputJar),
- "--output=" + IOUtil.absolutePathString(remapped),
- "--map=" + IOUtil.absolutePathString(this.mojangMappings),
- "--reverse")
- .withArgs(this.classpath.stream()
- .map(IOUtil::absolutePathString)
- .map(s -> "--lib=" + s)
- .toList())
- .withArgs("--src-fix", "--strip-sigs", "--disable-abstract-param")
- .run();
-
- this.bind(InputJar.KEY).to(remapped);
- }
-}
diff --git a/src/main/java/io/papermc/codebook/pages/RemapLvtPage.java b/src/main/java/io/papermc/codebook/pages/RemapLvtPage.java
deleted file mode 100644
index 98105f0..0000000
--- a/src/main/java/io/papermc/codebook/pages/RemapLvtPage.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * codebook is a remapper utility for the PaperMC project.
- *
- * Copyright (c) 2023 Kyle Wood (DenWav)
- * Contributors
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 3 only, no later versions.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
- * USA
- */
-
-package io.papermc.codebook.pages;
-
-import dev.denwav.hypo.asm.AsmClassData;
-import dev.denwav.hypo.core.HypoContext;
-import io.papermc.codebook.exceptions.UnexpectedException;
-import io.papermc.codebook.lvt.LvtNamer;
-import io.papermc.codebook.report.Reports;
-import jakarta.inject.Inject;
-import java.io.IOException;
-import org.cadixdev.lorenz.MappingSet;
-import org.checkerframework.checker.nullness.qual.Nullable;
-
-public final class RemapLvtPage extends AsmProcessorPage {
-
- private final @Nullable MappingSet paramMappings;
- private final Reports reports;
- private @Nullable LvtNamer lvtNamer;
-
- @Inject
- public RemapLvtPage(
- @Hypo final HypoContext hypoContext,
- @ParamMappings @Nullable final MappingSet paramMappings,
- @Report final Reports reports) {
- super(hypoContext);
- this.paramMappings = paramMappings;
- this.reports = reports;
- }
-
- @Override
- public void exec() {
- if (this.paramMappings == null) {
- return;
- }
-
- try {
- this.lvtNamer = new LvtNamer(this.context, this.paramMappings, this.reports);
- } catch (final IOException e) {
- throw new UnexpectedException("Failed to create LVT namer", e);
- }
-
- this.processClasses();
- }
-
- @Override
- protected void processClass(final AsmClassData classData) throws IOException {
- if (this.lvtNamer != null) {
- this.lvtNamer.processClass(classData);
- }
- }
-}
diff --git a/src/main/java/io/papermc/codebook/pages/StripSignaturesPage.java b/src/main/java/io/papermc/codebook/pages/StripSignaturesPage.java
new file mode 100644
index 0000000..1e8f4c5
--- /dev/null
+++ b/src/main/java/io/papermc/codebook/pages/StripSignaturesPage.java
@@ -0,0 +1,168 @@
+/*
+ * codebook is a remapper utility for the PaperMC project.
+ *
+ * Copyright (c) 2023 Kyle Wood (DenWav)
+ * Contributors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 3 only, no later versions.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ */
+
+package io.papermc.codebook.pages;
+
+import io.papermc.codebook.exceptions.UnexpectedException;
+import io.papermc.codebook.util.IOUtil;
+import jakarta.inject.Inject;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.jar.Attributes;
+import java.util.jar.Manifest;
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+public final class StripSignaturesPage extends CodeBookPage {
+
+ private static final Map CREATE_FS_ARGS = Map.of("create", "true");
+ private static final String DIGEST_SUFFIX = "-digest";
+ private static final int DIGEST_SUFFIX_LENGTH = DIGEST_SUFFIX.length();
+
+ private final Path inputJar;
+ private final Path tempDir;
+
+ @Inject
+ public StripSignaturesPage(@InputJar final Path inputJar, @TempDir final Path tempDir) {
+ this.inputJar = inputJar;
+ this.tempDir = tempDir;
+ }
+
+ @Override
+ public void exec() {
+ try (final FileSystem inputFs = FileSystems.newFileSystem(this.inputJar)) {
+ final Path inputRoot = inputFs.getPath("/");
+ final @Nullable Manifest strippedManifest = stripManifestDigestEntries(inputRoot);
+ if (strippedManifest == null && !containsSignatureFiles(inputRoot)) {
+ return;
+ }
+
+ final Path strippedJar = this.tempDir.resolve("unsigned-" + this.inputJar.getFileName());
+ IOUtil.deleteIfExists(strippedJar);
+
+ try (final FileSystem outputFs = FileSystems.newFileSystem(strippedJar, CREATE_FS_ARGS)) {
+ copyContents(inputRoot, outputFs.getPath("/"), strippedManifest);
+ }
+
+ this.bind(InputJar.KEY).to(strippedJar);
+ } catch (final IOException e) {
+ throw new UnexpectedException("Failed to strip jar signatures", e);
+ }
+ }
+
+ private static boolean containsSignatureFiles(final Path inputRoot) throws IOException {
+ try (final var paths = Files.walk(inputRoot)) {
+ for (final Path path : (Iterable) paths::iterator) {
+ if (isSignatureFile(pathName(inputRoot.relativize(path)))) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private static void copyContents(
+ final Path inputRoot, final Path outputRoot, final @Nullable Manifest strippedManifest) throws IOException {
+ try (final var paths = Files.walk(inputRoot)) {
+ for (final Path sourcePath : (Iterable) paths::iterator) {
+ final Path relativePath = inputRoot.relativize(sourcePath);
+ final String entryName = pathName(relativePath);
+ if (entryName.isEmpty() || isSignatureFile(entryName)) {
+ continue;
+ }
+
+ final Path outputPath = outputRoot.resolve(relativePath.toString());
+ if (Files.isDirectory(sourcePath)) {
+ Files.createDirectories(outputPath);
+ } else if (strippedManifest != null && isManifestFile(entryName)) {
+ IOUtil.createParentDirectories(outputPath);
+ writeManifest(outputPath, strippedManifest);
+ } else {
+ IOUtil.createParentDirectories(outputPath);
+ Files.copy(sourcePath, outputPath);
+ }
+ }
+ }
+ }
+
+ private static @Nullable Manifest stripManifestDigestEntries(final Path inputRoot) throws IOException {
+ final Path manifestPath = inputRoot.resolve("META-INF/MANIFEST.MF");
+ if (Files.notExists(manifestPath)) {
+ return null;
+ }
+
+ final Manifest manifest;
+ try (final InputStream input = Files.newInputStream(manifestPath)) {
+ manifest = new Manifest(input);
+ }
+
+ boolean madeChanges = false;
+ for (final Iterator it = manifest.getEntries().values().iterator(); it.hasNext(); ) {
+ final Attributes entryAttributes = it.next();
+ if (entryAttributes.keySet().removeIf(StripSignaturesPage::isDigestAttribute)) {
+ madeChanges = true;
+ if (entryAttributes.isEmpty()) {
+ it.remove();
+ }
+ }
+ }
+
+ return madeChanges ? manifest : null;
+ }
+
+ private static boolean isDigestAttribute(final Object key) {
+ final String attributeName = key.toString();
+ if (attributeName.length() <= DIGEST_SUFFIX_LENGTH) {
+ return false;
+ }
+ return attributeName.regionMatches(
+ true, attributeName.length() - DIGEST_SUFFIX_LENGTH, DIGEST_SUFFIX, 0, DIGEST_SUFFIX_LENGTH);
+ }
+
+ private static boolean isSignatureFile(final String entryName) {
+ return entryName.startsWith("META-INF/")
+ && (entryName.endsWith(".RSA")
+ || entryName.endsWith(".SF")
+ || entryName.endsWith(".DSA")
+ || entryName.endsWith(".EC"));
+ }
+
+ private static boolean isManifestFile(final String entryName) {
+ return entryName.equals("META-INF/MANIFEST.MF");
+ }
+
+ private static String pathName(final Path relativePath) {
+ return relativePath.toString().replace('\\', '/');
+ }
+
+ private static void writeManifest(final Path outputPath, final Manifest manifest) throws IOException {
+ try (final OutputStream output = Files.newOutputStream(outputPath)) {
+ manifest.write(output);
+ }
+ }
+}
diff --git a/src/test/java/io/papermc/codebook/pages/StripSignaturesPageTest.java b/src/test/java/io/papermc/codebook/pages/StripSignaturesPageTest.java
new file mode 100644
index 0000000..9fe46af
--- /dev/null
+++ b/src/test/java/io/papermc/codebook/pages/StripSignaturesPageTest.java
@@ -0,0 +1,181 @@
+/*
+ * codebook is a remapper utility for the PaperMC project.
+ *
+ * Copyright (c) 2023 Kyle Wood (DenWav)
+ * Contributors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 3 only, no later versions.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+ * USA
+ */
+
+package io.papermc.codebook.pages;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Module;
+import java.io.IOException;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Map;
+import java.util.Set;
+import java.util.jar.Manifest;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+class StripSignaturesPageTest {
+
+ private static final Map CREATE_FS_ARGS = Map.of("create", "true");
+
+ @TempDir
+ Path tempDir;
+
+ @Test
+ void stripsSignatureFilesAndManifestDigests() throws IOException {
+ final Path inputJar = this.tempDir.resolve("input.jar");
+ createJar(
+ inputJar,
+ Map.of(
+ "/META-INF/MANIFEST.MF",
+ "Manifest-Version: 1.0\n\n"
+ + "Name: com/example/Test.class\n"
+ + "SHA-256-Digest: digest\n"
+ + "Magic: keep\n\n"
+ + "Name: com/example/Empty.class\n"
+ + "SHA1-Digest: digest\n\n",
+ "/META-INF/TEST.SF",
+ "signature",
+ "/META-INF/TEST.RSA",
+ "block",
+ "/META-INF/nested/TEST.EC",
+ "nested block",
+ "/META-INF/SIG-CODEBOOK",
+ "should remain",
+ "/meta-inf/LOWER.SF",
+ "should remain",
+ "/META-INF/services/test",
+ "service",
+ "/com/example/Test.class",
+ "class bytes"));
+
+ final Path rewrittenJar = execPage(inputJar, this.tempDir);
+ final Manifest manifest = readManifest(rewrittenJar);
+
+ assertNotEquals(inputJar, rewrittenJar);
+ assertEquals(
+ Set.of(
+ "/META-INF/MANIFEST.MF",
+ "/META-INF/SIG-CODEBOOK",
+ "/META-INF/services/test",
+ "/com/example/Test.class",
+ "/meta-inf/LOWER.SF"),
+ jarEntries(rewrittenJar));
+ assertEquals(
+ Set.of(
+ "/META-INF/MANIFEST.MF",
+ "/META-INF/SIG-CODEBOOK",
+ "/META-INF/TEST.SF",
+ "/META-INF/TEST.RSA",
+ "/META-INF/nested/TEST.EC",
+ "/META-INF/services/test",
+ "/com/example/Test.class",
+ "/meta-inf/LOWER.SF"),
+ jarEntries(inputJar));
+ assertEquals("keep", manifest.getEntries().get("com/example/Test.class").getValue("Magic"));
+ assertNull(manifest.getEntries().get("com/example/Test.class").getValue("SHA-256-Digest"));
+ assertNull(manifest.getEntries().get("com/example/Empty.class"));
+ }
+
+ @Test
+ void rewritesJarWhenOnlyManifestContainsDigestEntries() throws IOException {
+ final Path inputJar = this.tempDir.resolve("manifest-only.jar");
+ createJar(
+ inputJar,
+ Map.of(
+ "/META-INF/MANIFEST.MF",
+ "Manifest-Version: 1.0\n\n"
+ + "Name: com/example/Test.class\n"
+ + "SHA-256-Digest: digest\n"
+ + "Magic: keep\n\n",
+ "/com/example/Test.class",
+ "class bytes"));
+
+ final Path rewrittenJar = execPage(inputJar, this.tempDir);
+ final Manifest manifest = readManifest(rewrittenJar);
+
+ assertNotEquals(inputJar, rewrittenJar);
+ assertEquals("keep", manifest.getEntries().get("com/example/Test.class").getValue("Magic"));
+ assertNull(manifest.getEntries().get("com/example/Test.class").getValue("SHA-256-Digest"));
+ }
+
+ @Test
+ void keepsOriginalJarWhenNoSignatureFilesExist() throws IOException {
+ final Path inputJar = this.tempDir.resolve("unsigned.jar");
+ createJar(
+ inputJar,
+ Map.of(
+ "/META-INF/MANIFEST.MF", "Manifest-Version: 1.0\n",
+ "/META-INF/services/test", "service",
+ "/com/example/Test.class", "class bytes"));
+
+ final Path rewrittenJar = execPage(inputJar, this.tempDir);
+
+ assertEquals(inputJar, rewrittenJar);
+ }
+
+ private static Path execPage(final Path inputJar, final Path tempDir) {
+ final StripSignaturesPage page = new StripSignaturesPage(inputJar, tempDir);
+ final Module module = page.exec(new AbstractModule() {
+ @Override
+ protected void configure() {
+ this.bind(CodeBookPage.InputJar.KEY).toInstance(inputJar);
+ }
+ });
+ return Guice.createInjector(module).getInstance(CodeBookPage.InputJar.KEY);
+ }
+
+ private static void createJar(final Path jar, final Map entries) throws IOException {
+ try (final FileSystem fs = FileSystems.newFileSystem(jar, CREATE_FS_ARGS)) {
+ for (final var entry : entries.entrySet()) {
+ final Path path = fs.getPath(entry.getKey());
+ Files.createDirectories(path.getParent());
+ Files.writeString(path, entry.getValue());
+ }
+ }
+ }
+
+ private static Set jarEntries(final Path jar) throws IOException {
+ try (final FileSystem fs = FileSystems.newFileSystem(jar)) {
+ try (final var paths = Files.walk(fs.getPath("/"))) {
+ return paths.filter(Files::isRegularFile)
+ .map(Path::toString)
+ .collect(java.util.stream.Collectors.toSet());
+ }
+ }
+ }
+
+ private static Manifest readManifest(final Path jar) throws IOException {
+ try (final FileSystem fs = FileSystems.newFileSystem(jar)) {
+ try (final var input = Files.newInputStream(fs.getPath("/META-INF/MANIFEST.MF"))) {
+ return new Manifest(input);
+ }
+ }
+ }
+}