Skip to content

Commit 2dcc25c

Browse files
committed
Support injecting userdev specific files
1 parent 7e8f9bc commit 2dcc25c

2 files changed

Lines changed: 132 additions & 3 deletions

File tree

src/main/java/net/minecraftforge/mcmaven/impl/repo/forge/InjectTask.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public String name() {
5353

5454
private Task injectData(Task input) {
5555
return Task.named("injectData[" + this.name.getName() + "][" + mappings + ']',
56-
Task.deps(input),
56+
Task.deps(input, this.patcher.filterBinaryInjections()),
5757
() -> injectDataImpl(input, new File(this.build, "injected.jar"))
5858
);
5959
}
@@ -66,22 +66,29 @@ private File injectDataImpl(Task inputTask, File outputJar) {
6666

6767
var universals = new ArrayList<File>();
6868
for (var p : this.patcher.getStack()) {
69-
if (p.config.universal != null) {
69+
if (p.config.universal != null && p.config.universalFilters == null) {
7070
var universal = this.cache.maven().download(Artifact.from(p.config.universal));
7171
universals.add(universal);
7272
cache.add(universal);
7373
}
7474
}
7575

76+
var injectTask = this.patcher.filterBinaryInjections();
77+
var inject = injectTask != null ? injectTask.execute() : null;
78+
if (inject != null)
79+
cache.add("inject", inject);
80+
7681
if (Mavenizer.checkCache(outputJar, cache))
7782
return outputJar;
7883

7984
try {
8085
var jars = new ArrayList<>(universals);
8186

8287
jars.add(recompiledJar);
88+
if (inject != null)
89+
jars.add(inject);
8390

84-
FileUtils.mergeJars(outputJar, true, (file, name) -> file == recompiledJar || !name.endsWith(".class"), jars.toArray(File[]::new));
91+
FileUtils.mergeJars(outputJar, true, (file, name) -> (file == recompiledJar || file == inject) || !name.endsWith(".class"), jars.toArray(File[]::new));
8592
} catch (IOException e) {
8693
return Util.sneak(e);
8794
}

src/main/java/net/minecraftforge/mcmaven/impl/repo/forge/Patcher.java

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@
55
package net.minecraftforge.mcmaven.impl.repo.forge;
66

77
import java.io.File;
8+
import java.io.FileInputStream;
89
import java.io.FileNotFoundException;
910
import java.io.FileOutputStream;
1011
import java.io.IOException;
12+
import java.nio.charset.StandardCharsets;
1113
import java.util.ArrayList;
1214
import java.util.Collections;
1315
import java.util.HashMap;
@@ -16,10 +18,15 @@
1618
import java.util.Map;
1719
import java.util.Stack;
1820
import java.util.function.Consumer;
21+
import java.util.function.Function;
1922
import java.util.function.Predicate;
2023
import java.util.function.Supplier;
24+
import java.util.regex.Pattern;
2125
import java.util.stream.Collectors;
26+
import java.util.zip.ZipEntry;
2227
import java.util.zip.ZipFile;
28+
import java.util.zip.ZipInputStream;
29+
import java.util.zip.ZipOutputStream;
2330

2431
import io.codechicken.diffpatch.cli.PatchOperation;
2532
import io.codechicken.diffpatch.util.LogLevel;
@@ -70,6 +77,7 @@ public class Patcher implements Supplier<Task> {
7077
private final Task downloadSources;
7178
private final Task predecomp;
7279
private final Task last;
80+
private final Task filterBinaryInjections;
7381

7482
/**
7583
* Creates a new Patcher for the given Forge repo.
@@ -162,6 +170,17 @@ public class Patcher implements Supplier<Task> {
162170
}
163171

164172
this.last = last;
173+
174+
var needsFilter = false;
175+
for (var p : this.getStack()) {
176+
if (p.config.inject != null || p.config.universalFilters != null) {
177+
needsFilter = true;
178+
break;
179+
}
180+
}
181+
182+
this.filterBinaryInjections = needsFilter ? null :
183+
Task.named("filterBinaryInjections[" + this.name.getName() + ']', this::filterBinaryInjectionsImpl);
165184
}
166185

167186
private RuntimeException except(String message) {
@@ -215,6 +234,14 @@ public MCPSide getMCPSide() {
215234
return this.mcpSide == null ? this.parent.getMCPSide() : this.mcpSide;
216235
}
217236

237+
public String getName() {
238+
return this.name.getName();
239+
}
240+
241+
public Artifact getArtifact() {
242+
return this.name;
243+
}
244+
218245
public String getDataHash() {
219246
return this.dataHash;
220247
}
@@ -675,4 +702,99 @@ private File injectSourcesImpl(Task inputTask, File output) {
675702
cache.save();
676703
return output;
677704
}
705+
706+
public @Nullable Task filterBinaryInjections() {
707+
return this.filterBinaryInjections;
708+
}
709+
710+
private File filterBinaryInjectionsImpl() {
711+
var output = new File(this.build, "binary-injections.jar");
712+
var cache = Util.cache(output);
713+
cache.addKnown("data", this.getDataHash());
714+
715+
record Info(File file, Artifact artifact, Predicate<String> filter, Function<String, String> renamer) {}
716+
var files = new ArrayList<Info>();
717+
718+
for (var p : getStack()) {
719+
var prefix = p.config.inject;
720+
if (prefix != null) {
721+
cache.addKnown("parent-" + p.getName(), p.getDataHash());
722+
files.add(new Info(p.data, p.getArtifact(),
723+
name -> name.length() <= prefix.length() || !name.startsWith(prefix),
724+
name -> name.substring(prefix.length())
725+
));
726+
}
727+
728+
if (p.config.universal != null && p.config.universalFilters != null) {
729+
var artifact = Artifact.from(p.config.universal);
730+
var file = this.forge.getCache().maven().download(artifact);
731+
cache.add("universal-" + p.getName(), file);
732+
733+
Predicate<String> filter = null;
734+
for (var line : p.config.universalFilters) {
735+
var pattern = Pattern.compile(line);
736+
Predicate<String> matcher = s -> !pattern.matcher(s).matches();
737+
if (filter == null)
738+
filter = matcher;
739+
else
740+
filter = filter.or(matcher);
741+
}
742+
files.add(new Info(file, artifact, filter, Function.identity()));
743+
}
744+
}
745+
746+
if (Mavenizer.checkCache(output, cache))
747+
return output;
748+
749+
if (output.getParentFile() != null)
750+
output.getParentFile().mkdirs();
751+
752+
try (var zos = new ZipOutputStream(new FileOutputStream(output))) {
753+
var servicesLists = new HashMap<String, List<String>>();
754+
var seen = new HashSet<String>();
755+
for (var info : files) {
756+
try (var zin = new ZipInputStream(new FileInputStream(this.data))) {
757+
ZipEntry entry;
758+
while ((entry = zin.getNextEntry()) != null) {
759+
if (FileUtils.isBlockOrSF(entry.getName()))
760+
continue;
761+
if (info.filter().test(entry.getName()))
762+
continue;
763+
764+
String name = info.renamer.apply(entry.getName());
765+
766+
if (name.startsWith("META-INF/services/") && !entry.isDirectory()) {
767+
var existing = servicesLists.computeIfAbsent(name, _ -> new ArrayList<>());
768+
if (existing.size() > 0) {
769+
existing.add("");
770+
existing.add("# " + info.artifact());
771+
}
772+
existing.add(new String(zin.readAllBytes(), StandardCharsets.UTF_8));
773+
} else if (seen.add(name)) {
774+
var _new = new ZipEntry(name);
775+
_new.setTime(0);
776+
zos.putNextEntry(_new);
777+
zin.transferTo(zos);
778+
}
779+
}
780+
}
781+
}
782+
783+
for(var kv : servicesLists.entrySet()) {
784+
String name = kv.getKey();
785+
ZipEntry _new = new ZipEntry(name);
786+
_new.setTime(0);
787+
zos.putNextEntry(_new);
788+
for (var line : kv.getValue()) {
789+
zos.write(line.getBytes(StandardCharsets.UTF_8));
790+
zos.write('\n');
791+
}
792+
}
793+
} catch (IOException e) {
794+
return Util.sneak(e);
795+
}
796+
797+
cache.save();
798+
return output;
799+
}
678800
}

0 commit comments

Comments
 (0)