Skip to content

Commit 0c35f34

Browse files
authored
Merge pull request #22 from FabricCompatibilityLayers/feature/aw-remapping
Implement AccessWidener remapping.
2 parents b98562c + 1e0839e commit 0c35f34

File tree

11 files changed

+135
-45
lines changed

11 files changed

+135
-45
lines changed

build.gradle

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ dependencies {
4848
shadow(runtimeOnly('net.fabricmc:tiny-remapper:0.11.0')) {
4949
transitive = false
5050
}
51+
shadow(runtimeOnly('net.fabricmc:access-widener:2.1.0')) {
52+
transitive = false
53+
}
5154

5255
shadow(runtimeOnly('com.google.code.gson:gson:2.2.4')) {
5356
transitive = false
@@ -96,6 +99,7 @@ shadowJar {
9699

97100
relocate 'net.fabricmc.mappingio', 'fr.catcore.modremapperapi.impl.lib.mappingio'
98101
relocate 'net.fabricmc.tinyremapper', 'fr.catcore.modremapperapi.impl.lib.tinyremapper'
102+
relocate 'net.fabricmc.accesswidener', 'fr.catcore.modremapperapi.impl.lib.accesswidener'
99103
relocate 'com.google.gson', 'fr.catcore.modremapperapi.impl.lib.gson'
100104
}
101105

src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/DefaultModCandidate.java

Lines changed: 0 additions & 9 deletions
This file was deleted.
Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,26 @@
11
package io.github.fabriccompatibiltylayers.modremappingapi.impl;
22

3+
import org.jetbrains.annotations.Nullable;
4+
35
import java.nio.file.Path;
46

5-
public abstract class ModCandidate {
7+
public class ModCandidate {
68
public final String modName;
7-
public final String modId;
9+
public final @Nullable String accessWidenerName;
810

911
public final Path file;
1012
public final Path original;
1113

12-
protected ModCandidate(String modName, String modId, Path file, Path original) {
14+
public byte[] accessWidener;
15+
16+
public ModCandidate(String modName, @Nullable String accessWidenerName, Path file, Path original) {
1317
this.modName = modName;
14-
this.modId = modId;
18+
this.accessWidenerName = accessWidenerName;
1519
this.file = file;
1620
this.original = original;
1721
}
22+
23+
public ModCandidate(String modName, Path file, Path original) {
24+
this(modName, null, file, original);
25+
}
1826
}

src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/context/ModRemapperContext.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package io.github.fabriccompatibiltylayers.modremappingapi.impl.context;
22

33
import io.github.fabriccompatibiltylayers.modremappingapi.impl.LibraryHandler;
4+
import io.github.fabriccompatibiltylayers.modremappingapi.impl.ModCandidate;
45
import io.github.fabriccompatibiltylayers.modremappingapi.impl.mappings.MappingsRegistry;
56
import io.github.fabriccompatibiltylayers.modremappingapi.impl.remapper.RemappingFlags;
67
import net.fabricmc.tinyremapper.TinyRemapper;
@@ -12,7 +13,7 @@
1213

1314
public interface ModRemapperContext {
1415
void init();
15-
void remapMods(Map<Path, Path> pathMap);
16+
void remapMods(Map<ModCandidate, Path> pathMap);
1617
void afterRemap();
1718
void discoverMods(boolean remapClassEdits);
1819
void gatherRemappers();

src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/context/v1/ModRemapperV1Context.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,12 @@ public void init() {
7676
this.mappingsRegistry.generateAdditionalMappings();
7777
}
7878

79-
public void remapMods(Map<Path, Path> pathMap) {
79+
public void remapMods(Map<ModCandidate, Path> pathMap) {
8080
Constants.MAIN_LOGGER.debug("Starting jar remapping!");
8181
SoftLockFixer.preloadClasses();
8282
TinyRemapper remapper = ModTrRemapper.makeRemapper(this);
8383
Constants.MAIN_LOGGER.debug("Remapper created!");
84-
ModTrRemapper.remapMods(remapper, pathMap, this.mappingsRegistry);
84+
ModTrRemapper.remapMods(remapper, pathMap, this);
8585
Constants.MAIN_LOGGER.debug("Jar remapping done!");
8686

8787
this.mappingsRegistry.writeFullMappings();
@@ -94,10 +94,10 @@ public void afterRemap() {
9494

9595
@Override
9696
public void discoverMods(boolean remapClassEdits) {
97-
Map<Path, Path> modPaths = this.modDiscoverer.init(remappers, remapClassEdits, this);
97+
Map<ModCandidate, Path> modPaths = this.modDiscoverer.init(remappers, remapClassEdits, this);
9898

99-
for (Path path : modPaths.keySet()) {
100-
mappingsRegistry.addModMappings(path);
99+
for (ModCandidate candidate : modPaths.keySet()) {
100+
mappingsRegistry.addModMappings(candidate.original);
101101
}
102102

103103
mappingsRegistry.generateModMappings();

src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/context/v1/V1ModDiscoverer.java

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import fr.catcore.modremapperapi.utils.Constants;
44
import io.github.fabriccompatibiltylayers.modremappingapi.api.v1.ModRemapper;
5-
import io.github.fabriccompatibiltylayers.modremappingapi.impl.DefaultModCandidate;
65
import io.github.fabriccompatibiltylayers.modremappingapi.impl.ModCandidate;
76
import io.github.fabriccompatibiltylayers.modremappingapi.impl.compatibility.V0ModRemapper;
87
import io.github.fabriccompatibiltylayers.modremappingapi.impl.discover.BaseModDiscoverer;
@@ -24,7 +23,7 @@
2423
public class V1ModDiscoverer extends BaseModDiscoverer {
2524
private final Map<String, List<String>> excluded = new HashMap<>();
2625

27-
public Map<Path, Path> init(List<ModRemapper> modRemappers, boolean remapClassEdits, ModRemapperV1Context context) {
26+
public Map<ModCandidate, Path> init(List<ModRemapper> modRemappers, boolean remapClassEdits, ModRemapperV1Context context) {
2827
Set<String> modFolders = new HashSet<>();
2928

3029
for (ModRemapper remapper : modRemappers) {
@@ -66,11 +65,9 @@ public Map<Path, Path> init(List<ModRemapper> modRemappers, boolean remapClassEd
6665
throw new RuntimeException(e);
6766
}
6867

69-
Map<Path, Path> modPaths = mods.stream()
68+
Map<ModCandidate, Path> modPaths = mods.stream()
7069
.filter(entry -> Files.exists(entry.original))
71-
.collect(Collectors.groupingBy(entry -> entry.modId))
72-
.entrySet().stream()
73-
.collect(Collectors.toMap(entry -> entry.getValue().get(0).original, entry -> entry.getValue().get(0).file));
70+
.collect(Collectors.toMap(entry -> entry, entry -> entry.file));
7471

7572
if (!remapClassEdits) {
7673
modPaths = excludeClassEdits(modPaths, mainTempDir, context.getMappingsRegistry());
@@ -81,15 +78,15 @@ public Map<Path, Path> init(List<ModRemapper> modRemappers, boolean remapClassEd
8178

8279
private void handleV0Excluded(List<ModCandidate> mods) throws IOException, URISyntaxException {
8380
for (ModCandidate modCandidate : mods) {
84-
if (excluded.containsKey(modCandidate.modId)) {
81+
if (excluded.containsKey(modCandidate.modName)) {
8582
if (Files.isDirectory(modCandidate.file)) {
86-
for (String excluded : excluded.get(modCandidate.modId)) {
83+
for (String excluded : excluded.get(modCandidate.modName)) {
8784
if (Files.deleteIfExists(modCandidate.file.resolve(excluded))) {
8885
Constants.MAIN_LOGGER.debug("File deleted: " + modCandidate.file.resolve(excluded));
8986
}
9087
}
9188
} else {
92-
FileUtils.removeEntriesFromZip(modCandidate.file, excluded.get(modCandidate.modId));
89+
FileUtils.removeEntriesFromZip(modCandidate.file, excluded.get(modCandidate.modName));
9390
}
9491
}
9592
}
@@ -136,7 +133,7 @@ public Optional<ModCandidate> discoverFolderMod(Path folder, Path destinationFol
136133

137134
if (hasClasses[0]) {
138135
return Optional.of(
139-
new DefaultModCandidate(
136+
new ModCandidate(
140137
name,
141138
destination,
142139
folder
@@ -166,7 +163,7 @@ public Optional<ModCandidate> discoverFileMod(Path file, Path destinationFolder)
166163

167164
if (found) {
168165
return Optional.of(
169-
new DefaultModCandidate(
166+
new ModCandidate(
170167
modName,
171168
destinationFolder.resolve(fileName),
172169
file

src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/discover/BaseModDiscoverer.java

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,12 @@ public List<ModCandidate> discoverMods(Path folder, Path destination) throws IOE
4747
return mods;
4848
}
4949

50-
public Map<Path, Path> excludeClassEdits(Map<Path, Path> modPaths, Path tempFolder, MappingsRegistry mappingsRegistry) {
51-
Map<Path, Path> map = new HashMap<>();
52-
Map<Path, Path> convertMap = new HashMap<>();
50+
public Map<ModCandidate, Path> excludeClassEdits(Map<ModCandidate, Path> modPaths, Path tempFolder, MappingsRegistry mappingsRegistry) {
51+
Map<ModCandidate, Path> map = new HashMap<>();
52+
Map<ModCandidate, Path> convertMap = new HashMap<>();
5353

54-
for (Map.Entry<Path, Path> entry : modPaths.entrySet()) {
54+
for (Map.Entry<ModCandidate, Path> entry : modPaths.entrySet()) {
55+
ModCandidate modCandidate = entry.getKey();
5556
Path tempDir = tempFolder.resolve(entry.getValue().getParent().getFileName().toString());
5657

5758
if (!Files.exists(tempDir)) {
@@ -64,24 +65,30 @@ public Map<Path, Path> excludeClassEdits(Map<Path, Path> modPaths, Path tempFold
6465
}
6566

6667
Path tempFile = tempDir.resolve(entry.getValue().getFileName().toString());
67-
map.put(tempFile, entry.getValue());
68+
map.put(new ModCandidate(
69+
modCandidate.modName,
70+
modCandidate.accessWidenerName,
71+
modCandidate.file,
72+
tempFile
73+
), entry.getValue());
6874
convertMap.put(entry.getKey(), tempFile);
6975
}
7076

71-
List<Path> errored = new ArrayList<>();
77+
List<ModCandidate> errored = new ArrayList<>();
7278

73-
for (Map.Entry<Path, Path> entry : convertMap.entrySet()) {
79+
for (Map.Entry<ModCandidate, Path> entry : convertMap.entrySet()) {
80+
ModCandidate modCandidate = entry.getKey();
7481
try {
75-
if (Files.isDirectory(entry.getKey())) {
76-
FileUtils.zipFolder(entry.getKey(), entry.getValue());
82+
if (Files.isDirectory(modCandidate.original)) {
83+
FileUtils.zipFolder(modCandidate.original, entry.getValue());
7784
} else {
78-
Files.copy(entry.getKey(), entry.getValue(), StandardCopyOption.REPLACE_EXISTING);
85+
Files.copy(modCandidate.original, entry.getValue(), StandardCopyOption.REPLACE_EXISTING);
7986
}
8087

8188
FileUtils.removeEntriesFromZip(entry.getValue(), mappingsRegistry.getVanillaClassNames());
8289
} catch (IOException | URISyntaxException e) {
8390
e.printStackTrace();
84-
errored.add(entry.getValue());
91+
errored.add(modCandidate);
8592
}
8693
}
8794

src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/remapper/ModTrRemapper.java

Lines changed: 70 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,33 @@
11
package io.github.fabriccompatibiltylayers.modremappingapi.impl.remapper;
22

3+
import io.github.fabriccompatibiltylayers.modremappingapi.impl.ModCandidate;
34
import io.github.fabriccompatibiltylayers.modremappingapi.impl.context.ModRemapperContext;
45
import io.github.fabriccompatibiltylayers.modremappingapi.impl.mappings.MappingTreeHelper;
56
import io.github.fabriccompatibiltylayers.modremappingapi.impl.mappings.MappingsRegistry;
67
import io.github.fabriccompatibiltylayers.modremappingapi.impl.remapper.minecraft.MinecraftRemapper;
78
import io.github.fabriccompatibiltylayers.modremappingapi.impl.remapper.resource.RefmapRemapper;
89
import io.github.fabriccompatibiltylayers.modremappingapi.impl.remapper.visitor.MixinPostApplyVisitor;
10+
import io.github.fabriccompatibiltylayers.modremappingapi.impl.utils.FileUtils;
11+
import net.fabricmc.accesswidener.AccessWidenerReader;
12+
import net.fabricmc.accesswidener.AccessWidenerRemapper;
13+
import net.fabricmc.accesswidener.AccessWidenerWriter;
914
import net.fabricmc.loader.api.FabricLoader;
1015
import net.fabricmc.mappingio.tree.MappingTree;
1116
import net.fabricmc.tinyremapper.NonClassCopyMode;
1217
import net.fabricmc.tinyremapper.OutputConsumerPath;
1318
import net.fabricmc.tinyremapper.TinyRemapper;
1419
import net.fabricmc.tinyremapper.extension.mixin.MixinExtension;
1520
import org.jetbrains.annotations.ApiStatus;
21+
import org.jetbrains.annotations.Nullable;
22+
import org.objectweb.asm.commons.Remapper;
1623

1724
import java.io.IOException;
25+
import java.nio.file.FileSystem;
26+
import java.nio.file.Files;
1827
import java.nio.file.Path;
1928
import java.util.*;
29+
import java.util.function.Consumer;
30+
import java.util.stream.Collectors;
2031

2132
@ApiStatus.Internal
2233
public class ModTrRemapper {
@@ -61,12 +72,69 @@ public static TinyRemapper makeRemapper(ModRemapperContext context) {
6172
return remapper;
6273
}
6374

64-
public static void remapMods(TinyRemapper remapper, Map<Path, Path> paths, MappingsRegistry mappingsRegistry) {
75+
public static void remapMods(TinyRemapper remapper, Map<ModCandidate, Path> paths, ModRemapperContext context) {
6576
List<OutputConsumerPath> outputConsumerPaths = new ArrayList<>();
6677

6778
List<OutputConsumerPath.ResourceRemapper> resourceRemappers = new ArrayList<>(NonClassCopyMode.FIX_META_INF.remappers);
6879
resourceRemappers.add(new RefmapRemapper());
6980

70-
TrRemapperHelper.applyRemapper(remapper, paths, outputConsumerPaths, resourceRemappers, true, mappingsRegistry.getSourceNamespace(), mappingsRegistry.getTargetNamespace());
81+
Consumer<TinyRemapper> consumer = getRemapperConsumer(paths, context);
82+
83+
TrRemapperHelper.applyRemapper(
84+
remapper,
85+
paths.entrySet().stream().collect(Collectors.toMap(entry -> entry.getKey().original, Map.Entry::getValue)),
86+
outputConsumerPaths,
87+
resourceRemappers,
88+
true,
89+
context.getMappingsRegistry().getSourceNamespace(),
90+
context.getMappingsRegistry().getTargetNamespace(),
91+
consumer
92+
);
93+
94+
if (context.getRemappingFlags().contains(RemappingFlags.ACCESS_WIDENER)) {
95+
for (Map.Entry<ModCandidate, Path> entry : paths.entrySet()) {
96+
ModCandidate candidate = entry.getKey();
97+
Path jarPath = entry.getValue();
98+
99+
if (candidate.accessWidenerName != null && candidate.accessWidener != null) {
100+
try (FileSystem fs = FileUtils.getJarFileSystem(jarPath)) {
101+
Files.delete(fs.getPath(candidate.accessWidenerName));
102+
Files.write(fs.getPath(candidate.accessWidenerName), candidate.accessWidener);
103+
} catch (Throwable t) {
104+
throw new RuntimeException("Error while writing remapped access widener for '" + candidate.modName + "'", t);
105+
}
106+
}
107+
}
108+
}
109+
}
110+
111+
private static @Nullable Consumer<TinyRemapper> getRemapperConsumer(Map<ModCandidate, Path> paths, ModRemapperContext context) {
112+
Consumer<TinyRemapper> consumer = null;
113+
114+
if (context.getRemappingFlags().contains(RemappingFlags.ACCESS_WIDENER)) {
115+
consumer = (currentRemapper) -> {
116+
for (Map.Entry<ModCandidate, Path> entry : paths.entrySet()) {
117+
ModCandidate candidate = entry.getKey();
118+
119+
if (candidate.accessWidenerName != null) {
120+
try (FileSystem jarFs = FileUtils.getJarFileSystem(candidate.original)) {
121+
candidate.accessWidener = remapAccessWidener(Files.readAllBytes(jarFs.getPath(candidate.accessWidenerName)), currentRemapper.getRemapper(), context.getMappingsRegistry().getTargetNamespace());
122+
} catch (Throwable t) {
123+
throw new RuntimeException("Error while remapping access widener for '" + candidate.modName + "'", t);
124+
}
125+
}
126+
}
127+
};
128+
}
129+
130+
return consumer;
131+
}
132+
133+
private static byte[] remapAccessWidener(byte[] data, Remapper remapper, String targetNamespace) {
134+
AccessWidenerWriter writer = new AccessWidenerWriter();
135+
AccessWidenerRemapper remappingDecorator = new AccessWidenerRemapper(writer, remapper, "intermediary", targetNamespace);
136+
AccessWidenerReader accessWidenerReader = new AccessWidenerReader(remappingDecorator);
137+
accessWidenerReader.read(data, "intermediary");
138+
return writer.write();
71139
}
72140
}

src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/remapper/RemappingFlags.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@
44

55
@ApiStatus.Internal
66
public enum RemappingFlags {
7-
MIXIN
7+
MIXIN,
8+
ACCESS_WIDENER
89
}

src/main/java/io/github/fabriccompatibiltylayers/modremappingapi/impl/remapper/TrRemapperHelper.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,22 @@
66
import net.fabricmc.tinyremapper.OutputConsumerPath;
77
import net.fabricmc.tinyremapper.TinyRemapper;
88
import org.jetbrains.annotations.ApiStatus;
9+
import org.jetbrains.annotations.Nullable;
910

1011
import java.io.IOException;
1112
import java.nio.file.Path;
1213
import java.util.HashMap;
1314
import java.util.List;
1415
import java.util.Map;
16+
import java.util.function.Consumer;
1517

1618
@ApiStatus.Internal
1719
public class TrRemapperHelper {
1820
public static void applyRemapper(TinyRemapper remapper, Map<Path, Path> paths, List<OutputConsumerPath> outputConsumerPaths, List<OutputConsumerPath.ResourceRemapper> resourceRemappers, boolean analyzeMapping, String srcNamespace, String targetNamespace) {
21+
applyRemapper(remapper, paths, outputConsumerPaths, resourceRemappers, analyzeMapping, srcNamespace, targetNamespace, null);
22+
}
23+
24+
public static void applyRemapper(TinyRemapper remapper, Map<Path, Path> paths, List<OutputConsumerPath> outputConsumerPaths, List<OutputConsumerPath.ResourceRemapper> resourceRemappers, boolean analyzeMapping, String srcNamespace, String targetNamespace, @Nullable Consumer<TinyRemapper> action) {
1925
try {
2026
Map<Path, InputTag> tagMap = new HashMap<>();
2127

@@ -43,6 +49,8 @@ public static void applyRemapper(TinyRemapper remapper, Map<Path, Path> paths, L
4349
}
4450

4551
if (analyzeMapping) ModRemappingAPIImpl.getCurrentContext().getMappingsRegistry().completeMappingsFromTr(remapper.getEnvironment(), srcNamespace);
52+
53+
if (action != null) action.accept(remapper);
4654
} catch (Exception e) {
4755
remapper.finish();
4856
outputConsumerPaths.forEach(o -> {

0 commit comments

Comments
 (0)