Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inject interfaces to vanilla classes using JST #1765

Merged
merged 15 commits into from
Dec 15, 2024
28 changes: 11 additions & 17 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -72,28 +72,22 @@ immaculate {
return fileContents
}

def interfaceChange = Pattern.compile('^[-+].*(implements|(interface.*extends)).*\$', Pattern.UNIX_LINES | Pattern.MULTILINE)
custom 'noInterfaceRemoval', { String fileContents ->
def interfaceChanges = fileContents.findAll(interfaceChange)
def interfaceChange = Pattern.compile('[-+].*(implements|(interface.*extends))(.*)\\{')
custom 'noInterfaceModifications', { String fileContents ->
def interfaceChanges = fileContents.lines().filter { it.matches(interfaceChange) }.toList()
if (interfaceChanges.isEmpty()) return fileContents
String removalChange = ""
String oldInterfaces = ""
// we expect interface additions/removals in pairs of - and then +
interfaceChanges.each { String change ->
final match = change =~ interfaceChange
match.find()
final values = match.group(3).trim()
if (change.startsWith('-')) {
//Skip the - and the ending brace
int implementsIndex = change.indexOf("implements")
if (implementsIndex == -1) implementsIndex = change.indexOf("extends")
//It should never still be -1 based on our initial matching regex, but if it does fail so we can figure out why
if (implementsIndex == -1) implementsIndex = 1
removalChange = change.substring(implementsIndex, change.length() - 1).trim()
} else if (!removalChange.isEmpty() && !change.contains(removalChange)) {
throw new GradleException("Removal of interfaces via patches is not allowed!")
} else {
removalChange = ""
oldInterfaces = values
} else if (oldInterfaces != values) {
throw new GradleException("Modification of interfaces via patches is not allowed!")
}
}
if (!removalChange.isEmpty()) {
throw new GradleException("Removal of interfaces via patches is not allowed!")
}
return fileContents
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.tasks.InputDirectory;
import org.gradle.api.tasks.InputFile;
import org.gradle.api.tasks.Optional;
import org.gradle.api.tasks.OutputDirectory;
import org.gradle.api.tasks.OutputFile;
import org.gradle.api.tasks.PathSensitive;
import org.gradle.api.tasks.PathSensitivity;
Expand All @@ -25,9 +27,14 @@ abstract class GenerateSourcePatches extends DefaultTask {
@PathSensitive(PathSensitivity.RELATIVE)
public abstract DirectoryProperty getModifiedSources();

@Optional
@OutputFile
public abstract RegularFileProperty getPatchesJar();

@Optional
@OutputDirectory
public abstract DirectoryProperty getPatchesFolder();
Technici4n marked this conversation as resolved.
Show resolved Hide resolved

@Inject
public GenerateSourcePatches() {}

Expand All @@ -37,7 +44,7 @@ public void generateSourcePatches() throws IOException {
.logTo(getLogger()::lifecycle)
.baseInput(MultiInput.detectedArchive(getOriginalJar().get().getAsFile().toPath()))
.changedInput(MultiInput.folder(getModifiedSources().get().getAsFile().toPath()))
.patchesOutput(MultiOutput.detectedArchive(getPatchesJar().get().getAsFile().toPath()))
.patchesOutput(getPatchesJar().isPresent() ? MultiOutput.detectedArchive(getPatchesJar().get().getAsFile().toPath()) : MultiOutput.folder(getPatchesFolder().getAsFile().get().toPath()))
.autoHeader(true)
.level(io.codechicken.diffpatch.util.LogLevel.WARN)
.summary(false)
Expand Down
52 changes: 35 additions & 17 deletions buildSrc/src/main/java/net/neoforged/neodev/NeoDevPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -100,24 +100,39 @@ public void apply(Project project) {
);
var applyAt = configureAccessTransformer(
project,
configurations,
createSourceArtifacts,
neoDevBuildDir,
atFiles);

applyAt.configure(task -> task.mustRunAfter(genAtsTask));

// 3. Apply patches to the source jar from 2.
// 3. Apply interface injections after the ATs
// this jar is only used for the patches in the repo
var applyInterfaceInjection = project.getTasks().register("applyInterfaceInjection", TransformSources.class, task -> {
task.getInputJar().set(applyAt.flatMap(TransformSources::getOutputJar));
task.getInterfaceInjectionData().from(project.getRootProject().file("src/main/resources/META-INF/injected-interfaces.json"));
task.getOutputJar().set(neoDevBuildDir.map(dir -> dir.file("artifacts/interface-injected-sources.jar")));
});

tasks.withType(TransformSources.class, task -> {
task.setGroup(INTERNAL_GROUP);
task.classpath(configurations.getExecutableTool(Tools.JST));

task.getLibraries().from(configurations.neoFormClasspath);
task.getLibrariesFile().set(neoDevBuildDir.map(dir -> dir.file("minecraft-libraries-for-" + task.getName() + ".txt")));
});

// 4. Apply patches to the source jar from 3.
var patchesFolder = project.getRootProject().file("patches");
var applyPatches = tasks.register("applyPatches", ApplyPatches.class, task -> {
task.setGroup(INTERNAL_GROUP);
task.getOriginalJar().set(applyAt.flatMap(ApplyAccessTransformer::getOutputJar));
task.getOriginalJar().set(applyInterfaceInjection.flatMap(TransformSources::getOutputJar));
task.getPatchesFolder().set(patchesFolder);
task.getPatchedJar().set(neoDevBuildDir.map(dir -> dir.file("artifacts/patched-sources.jar")));
task.getRejectsFolder().set(project.getRootProject().file("rejects"));
});

// 4. Unpack jar from 3.
// 5. Unpack jar from 4.
var mcSourcesPath = project.file("src/main/java");
tasks.register("setup", Sync.class, task -> {
task.setGroup(GROUP);
Expand Down Expand Up @@ -185,14 +200,22 @@ public void apply(Project project) {
* OTHER TASKS
*/

// Generate source patches into a patch archive.
// Generate source patches into a patch archive, based on the jar with injected interfaces.
var genSourcePatches = tasks.register("generateSourcePatches", GenerateSourcePatches.class, task -> {
task.setGroup(INTERNAL_GROUP);
task.getOriginalJar().set(applyAt.flatMap(ApplyAccessTransformer::getOutputJar));
task.getOriginalJar().set(applyInterfaceInjection.flatMap(TransformSources::getOutputJar));
task.getModifiedSources().set(project.file("src/main/java"));
task.getPatchesJar().set(neoDevBuildDir.map(dir -> dir.file("source-patches.zip")));
});

// Generate source patches that are based on the production environment (without separate interface injection)
var genProductionPatches = tasks.register("generateProductionSourcePatches", GenerateSourcePatches.class, task -> {
task.setGroup(INTERNAL_GROUP);
task.getOriginalJar().set(applyAt.flatMap(TransformSources::getOutputJar));
task.getModifiedSources().set(project.file("src/main/java"));
task.getPatchesFolder().set(neoDevBuildDir.map(dir -> dir.dir("production-source-patches")));
});

// Update the patch/ folder with the current patches.
tasks.register("genPatches", Sync.class, task -> {
task.setGroup(GROUP);
Expand Down Expand Up @@ -245,7 +268,7 @@ public void apply(Project project) {
configurations,
createCleanArtifacts,
neoDevBuildDir,
patchesFolder
genProductionPatches.flatMap(GenerateSourcePatches::getPatchesFolder)
);

// Launcher profile = the version.json file used by the Minecraft launcher.
Expand Down Expand Up @@ -411,7 +434,7 @@ public void apply(Project project) {
task.from(binaryPatchOutputs.binaryPatchesForMerged(), spec -> {
spec.rename(s -> "joined.lzma");
});
task.from(project.zipTree(genSourcePatches.flatMap(GenerateSourcePatches::getPatchesJar)), spec -> {
task.from(project.fileTree(genProductionPatches.flatMap(GenerateSourcePatches::getPatchesFolder)), spec -> {
spec.into("patches/");
});
});
Expand Down Expand Up @@ -444,32 +467,27 @@ public void apply(Project project) {
setupProductionServerTest(project, installerJar);
}

private static TaskProvider<ApplyAccessTransformer> configureAccessTransformer(
private static TaskProvider<TransformSources> configureAccessTransformer(
Project project,
NeoDevConfigurations configurations,
TaskProvider<CreateMinecraftArtifacts> createSourceArtifacts,
Provider<Directory> neoDevBuildDir,
List<File> atFiles) {

// Pass -PvalidateAccessTransformers to validate ATs.
var validateAts = project.getProviders().gradleProperty("validateAccessTransformers").map(p -> true).orElse(false);
return project.getTasks().register("applyAccessTransformer", ApplyAccessTransformer.class, task -> {
task.setGroup(INTERNAL_GROUP);
task.classpath(configurations.getExecutableTool(Tools.JST));
return project.getTasks().register("applyAccessTransformer", TransformSources.class, task -> {
task.getInputJar().set(createSourceArtifacts.flatMap(CreateMinecraftArtifacts::getSourcesArtifact));
task.getAccessTransformers().from(atFiles);
task.getValidate().set(validateAts);
task.getValidateAccessTransformers().set(validateAts);
task.getOutputJar().set(neoDevBuildDir.map(dir -> dir.file("artifacts/access-transformed-sources.jar")));
task.getLibraries().from(configurations.neoFormClasspath);
task.getLibrariesFile().set(neoDevBuildDir.map(dir -> dir.file("minecraft-libraries-for-jst.txt")));
});
}

private static BinaryPatchOutputs configureBinaryPatchCreation(Project project,
NeoDevConfigurations configurations,
TaskProvider<CreateCleanArtifacts> createCleanArtifacts,
Provider<Directory> neoDevBuildDir,
File sourcesPatchesFolder) {
Provider<Directory> sourcesPatchesFolder) {
Matyrobbrt marked this conversation as resolved.
Show resolved Hide resolved
var tasks = project.getTasks();

var artConfig = configurations.getExecutableTool(Tools.AUTO_RENAMING_TOOL);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.gradle.api.tasks.InputFiles;
import org.gradle.api.tasks.Internal;
import org.gradle.api.tasks.JavaExec;
import org.gradle.api.tasks.Optional;
import org.gradle.api.tasks.OutputFile;
import org.gradle.api.tasks.TaskAction;

Expand All @@ -22,20 +23,23 @@
import java.util.Arrays;

/**
* Runs <a href="https://github.com/neoforged/JavaSourceTransformer">JavaSourceTransformer</a> to apply
* access transformers to the Minecraft source code for extending the access level of existing classes/methods/etc.
* <p>
* Note that at runtime, FML also applies access transformers.
* Runs <a href="https://github.com/neoforged/JavaSourceTransformer">JavaSourceTransformer</a> over the Minecraft source code.
*/
abstract class ApplyAccessTransformer extends JavaExec {
@InputFile
public abstract RegularFileProperty getInputJar();

abstract class TransformSources extends JavaExec {
@Optional
@InputFiles
public abstract ConfigurableFileCollection getAccessTransformers();

@Input
public abstract Property<Boolean> getValidate();
@Optional
public abstract Property<Boolean> getValidateAccessTransformers();

@Optional
@InputFiles
public abstract ConfigurableFileCollection getInterfaceInjectionData();

@InputFile
public abstract RegularFileProperty getInputJar();

@OutputFile
public abstract RegularFileProperty getOutputJar();
Expand All @@ -48,7 +52,7 @@ abstract class ApplyAccessTransformer extends JavaExec {
public abstract RegularFileProperty getLibrariesFile();

@Inject
public ApplyAccessTransformer() {}
public TransformSources() {}

@Override
@TaskAction
Expand All @@ -63,15 +67,29 @@ public void exec() {
}

var args = new ArrayList<>(Arrays.asList(
"--enable-accesstransformers",
"--access-transformer-validation", getValidate().get() ? "error" : "log",
"--libraries-list", getLibrariesFile().getAsFile().get().getAbsolutePath()
));

for (var file : getAccessTransformers().getFiles()) {
if (!getAccessTransformers().isEmpty()) {
args.addAll(Arrays.asList(
"--access-transformer", file.getAbsolutePath()
"--enable-accesstransformers",
"--access-transformer-validation", getValidateAccessTransformers().get() ? "error" : "log"
));
for (var file : getAccessTransformers().getFiles()) {
args.addAll(Arrays.asList(
"--access-transformer", file.getAbsolutePath()
));
}
}

if (!getInterfaceInjectionData().isEmpty()) {
args.add("--enable-interface-injection");

for (var file : getInterfaceInjectionData().getFiles()) {
args.addAll(Arrays.asList(
"--interface-injection-data", file.getAbsolutePath()
));
}
}

args.addAll(Arrays.asList(
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ neoform_version=20241203.161809
neoforge_snapshot_next_stable=21.5

# renovate: net.neoforged.jst:jst-cli-bundle
jst_version=1.0.45
jst_version=1.0.67
legacyinstaller_version=3.0.+
# renovate: net.neoforged:AutoRenamingTool
art_version=2.0.3
Expand Down
11 changes: 0 additions & 11 deletions patches/com/mojang/blaze3d/vertex/PoseStack.java.patch

This file was deleted.

9 changes: 0 additions & 9 deletions patches/com/mojang/blaze3d/vertex/VertexConsumer.java.patch
Original file line number Diff line number Diff line change
@@ -1,14 +1,5 @@
--- a/com/mojang/blaze3d/vertex/VertexConsumer.java
+++ b/com/mojang/blaze3d/vertex/VertexConsumer.java
@@ -13,7 +_,7 @@
import org.lwjgl.system.MemoryStack;

@OnlyIn(Dist.CLIENT)
-public interface VertexConsumer {
+public interface VertexConsumer extends net.neoforged.neoforge.client.extensions.IVertexConsumerExtension {
VertexConsumer addVertex(float p_350761_, float p_350704_, float p_350711_);

VertexConsumer setColor(int p_350535_, int p_350875_, int p_350886_, int p_350775_);
@@ -131,11 +_,14 @@
f5 = p_331397_[i1] * p_85992_ * 255.0F;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,14 @@
@OnlyIn(Dist.CLIENT)
public static enum Type {
FLOAT(4, "Float", 5126),
@@ -113,7 +_,8 @@
@@ -113,6 +_,7 @@
}

@OnlyIn(Dist.CLIENT)
- public static enum Usage {
+ @net.neoforged.fml.common.asm.enumextension.NamedEnum
+ public static enum Usage implements net.neoforged.fml.common.asm.enumextension.IExtensibleEnum {
public static enum Usage implements net.neoforged.fml.common.asm.enumextension.IExtensibleEnum {
POSITION(
"Position",
(p_349733_, p_349734_, p_349735_, p_349736_, p_349737_) -> GlStateManager._vertexAttribPointer(
@@ -163,6 +_,10 @@
@OnlyIn(Dist.CLIENT)
public interface SetupState {
Expand Down
23 changes: 7 additions & 16 deletions patches/com/mojang/math/Transformation.java.patch
Original file line number Diff line number Diff line change
@@ -1,20 +1,9 @@
--- a/com/mojang/math/Transformation.java
+++ b/com/mojang/math/Transformation.java
@@ -13,7 +_,7 @@
import org.joml.Quaternionf;
import org.joml.Vector3f;

-public final class Transformation {
+public final class Transformation implements net.neoforged.neoforge.common.extensions.ITransformationExtension {
private final Matrix4f matrix;
public static final Codec<Transformation> CODEC = RecordCodecBuilder.create(
p_269604_ -> p_269604_.group(
@@ -157,6 +_,19 @@
@Override
public int hashCode() {
@@ -159,6 +_,19 @@
return Objects.hash(this.matrix);
+ }
+
}
+ private Matrix3f normalTransform = null;
+ public Matrix3f getNormalMatrix() {
+ checkNormalTransform();
Expand All @@ -26,6 +15,8 @@
+ normalTransform.invert();
+ normalTransform.transpose();
+ }
}
+ }
+
public Transformation slerp(Transformation p_175938_, float p_175939_) {
Vector3f vector3f = this.getTranslation();
Quaternionf quaternionf = this.getLeftRotation();
9 changes: 0 additions & 9 deletions patches/net/minecraft/advancements/Advancement.java.patch
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,3 @@

public Advancement(
Optional<ResourceLocation> p_300893_,
@@ -111,7 +_,7 @@
});
}

- public static class Builder {
+ public static class Builder implements net.neoforged.neoforge.common.extensions.IAdvancementBuilderExtension {
private Optional<ResourceLocation> parent = Optional.empty();
private Optional<DisplayInfo> display = Optional.empty();
private AdvancementRewards rewards = AdvancementRewards.EMPTY;
7 changes: 2 additions & 5 deletions patches/net/minecraft/client/KeyMapping.java.patch
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
--- a/net/minecraft/client/KeyMapping.java
+++ b/net/minecraft/client/KeyMapping.java
@@ -15,9 +_,9 @@
import net.neoforged.api.distmarker.OnlyIn;

@@ -17,7 +_,7 @@
@OnlyIn(Dist.CLIENT)
-public class KeyMapping implements Comparable<KeyMapping> {
+public class KeyMapping implements Comparable<KeyMapping>, net.neoforged.neoforge.client.extensions.IKeyMappingExtension {
public class KeyMapping implements Comparable<KeyMapping>, net.neoforged.neoforge.client.extensions.IKeyMappingExtension {
private static final Map<String, KeyMapping> ALL = Maps.newHashMap();
- private static final Map<InputConstants.Key, KeyMapping> MAP = Maps.newHashMap();
+ private static final net.neoforged.neoforge.client.settings.KeyMappingLookup MAP = new net.neoforged.neoforge.client.settings.KeyMappingLookup();
Expand Down
Loading
Loading