6
6
import cpw .mods .jarhandling .JarContents ;
7
7
import cpw .mods .jarhandling .JarContentsBuilder ;
8
8
import cpw .mods .jarhandling .SecureJar ;
9
+ import cpw .mods .modlauncher .Launcher ;
10
+ import cpw .mods .modlauncher .api .IModuleLayerManager ;
11
+ import net .fabricmc .loader .impl .metadata .LoaderModMetadata ;
9
12
import net .fabricmc .loader .impl .metadata .NestedJarEntry ;
10
13
import net .neoforged .fml .ModLoadingException ;
11
14
import net .neoforged .fml .loading .FMLPaths ;
14
17
import net .neoforged .fml .loading .moddiscovery .readers .JarModsDotTomlModFileReader ;
15
18
import net .neoforged .fml .loading .progress .StartupNotificationManager ;
16
19
import net .neoforged .neoforgespi .language .IModInfo ;
17
- import net .neoforged .neoforgespi .locating .IDependencyLocator ;
18
- import net .neoforged .neoforgespi .locating .IDiscoveryPipeline ;
19
- import net .neoforged .neoforgespi .locating .IModFile ;
20
- import net .neoforged .neoforgespi .locating .IncompatibleFileReporting ;
21
- import net .neoforged .neoforgespi .locating .ModFileDiscoveryAttributes ;
20
+ import net .neoforged .neoforgespi .locating .*;
22
21
import org .apache .maven .artifact .versioning .ArtifactVersion ;
23
22
import org .apache .maven .artifact .versioning .DefaultArtifactVersion ;
24
23
import org .jetbrains .annotations .Nullable ;
25
24
import org .sinytra .connector .ConnectorEarlyLoader ;
26
25
import org .sinytra .connector .locator .filter .ForgeModPackageFilter ;
27
26
import org .sinytra .connector .locator .filter .SplitPackageMerger ;
27
+ import org .sinytra .connector .locator .transform .ConnectorTransformerEnvironment ;
28
+ import org .sinytra .connector .transformer .TransformerEnvironment ;
28
29
import org .sinytra .connector .transformer .jar .JarTransformer ;
29
30
import org .sinytra .connector .util .ConnectorUtil ;
30
31
import org .sinytra .connector .util .PriorityModLoadingException ;
34
35
import java .lang .module .ModuleDescriptor ;
35
36
import java .nio .file .Files ;
36
37
import java .nio .file .Path ;
37
- import java .util .ArrayList ;
38
- import java .util .Collection ;
39
- import java .util .Comparator ;
40
- import java .util .List ;
41
- import java .util .Objects ;
42
- import java .util .Optional ;
38
+ import java .util .*;
43
39
import java .util .stream .Collectors ;
44
40
import java .util .stream .Stream ;
45
41
46
42
import static cpw .mods .modlauncher .api .LambdaExceptionUtils .rethrowFunction ;
47
43
import static cpw .mods .modlauncher .api .LambdaExceptionUtils .uncheck ;
48
44
import static net .neoforged .fml .loading .LogMarkers .SCAN ;
49
- import static org .sinytra .connector .transformer .jar .JarTransformer .cacheTransformableJar ;
50
45
51
46
public class ConnectorLocator implements IDependencyLocator {
52
47
public static final String PLACEHOLDER_PROPERTY = "connector:placeholder" ;
@@ -63,13 +58,14 @@ public void scanMods(List<IModFile> loadedMods, IDiscoveryPipeline pipeline) {
63
58
LOGGER .error ("Skipping mod scan due to previously encountered error" );
64
59
return ;
65
60
}
61
+
66
62
try {
67
- List < IModFile > results = locateFabricMods (loadedMods );
63
+ LocationResult results = locateFabricMods (loadedMods );
68
64
if (results != null ) {
69
- results .forEach (pipeline ::addModFile );
65
+ results .mods (). forEach (pipeline ::addModFile );
70
66
71
67
// Create mod file for generated adapter mixins jar
72
- Path generatedAdapterJar = JarTransformer . getGeneratedJarPath ();
68
+ Path generatedAdapterJar = results . generatedJarPath ();
73
69
if (Files .exists (generatedAdapterJar )) {
74
70
pipeline .addPath (generatedAdapterJar , ModFileDiscoveryAttributes .DEFAULT , IncompatibleFileReporting .ERROR );
75
71
}
@@ -93,28 +89,37 @@ public void scanMods(List<IModFile> loadedMods, IDiscoveryPipeline pipeline) {
93
89
}
94
90
95
91
@ Nullable
96
- private List < IModFile > locateFabricMods (List <IModFile > discoveredMods ) {
92
+ private LocationResult locateFabricMods (List <IModFile > discoveredMods ) {
97
93
LOGGER .debug (SCAN , "Scanning mods dir {} for mods" , FMLPaths .MODSDIR .get ());
98
94
Path tempDir = ConnectorUtil .CONNECTOR_FOLDER .resolve ("temp" );
99
95
100
96
// Get all existing mods
101
97
Collection <SimpleModInfo > loadedModInfos = getPreviouslyDiscoveredMods (discoveredMods );
102
98
Collection <IModFile > loadedModFiles = loadedModInfos .stream ().map (SimpleModInfo ::origin ).toList ();
103
99
Collection <String > loadedModIds = loadedModInfos .stream ().filter (mod -> !mod .library ()).map (SimpleModInfo ::modid ).collect (Collectors .toUnmodifiableSet ());
104
- Collection <String > loadedModuleNames = loadedModInfos .stream ().filter (SimpleModInfo ::library ).map (SimpleModInfo ::moduleName ).filter (Objects ::nonNull ).collect (Collectors .toUnmodifiableSet ());
100
+ Collection <String > loadedModuleNames = Stream .concat (
101
+ Launcher .INSTANCE .findLayerManager ().flatMap (m -> m .getLayer (IModuleLayerManager .Layer .BOOT ))
102
+ .stream ()
103
+ .flatMap (m -> m .modules ().stream ())
104
+ .map (Module ::getName ),
105
+ loadedModInfos .stream ().filter (SimpleModInfo ::library ).map (SimpleModInfo ::moduleName ).filter (Objects ::nonNull ))
106
+ .collect (Collectors .toUnmodifiableSet ());
107
+
108
+ TransformerEnvironment environment = new ConnectorTransformerEnvironment (loadedModFiles );
109
+ JarTransformer transformer = new JarTransformer (environment );
105
110
106
111
// Discover fabric mod jars
107
112
List <JarTransformer .TransformableJar > discoveredJars = FabricModsDiscoverer .scanFabricMods ()
108
- .map (rethrowFunction (p -> cacheTransformableJar (p .toFile ())))
113
+ .map (rethrowFunction (p -> transformer . cacheTransformableJar (p .toFile ())))
109
114
.filter (jar -> !shouldIgnoreMod (jar , loadedModIds , loadedModuleNames ))
110
115
.toList ();
111
116
112
117
// Discover fabric nested mod jars
113
118
Multimap <JarTransformer .TransformableJar , JarTransformer .TransformableJar > parentToChildren = HashMultimap .create ();
114
119
List <JarTransformer .TransformableJar > discoveredNestedJars = discoveredJars .stream ()
115
120
.flatMap (jar -> {
116
- ConnectorFabricModMetadata metadata = jar .modPath ().metadata ().modMetadata ();
117
- return shouldIgnoreMod (jar , loadedModIds , loadedModuleNames ) ? Stream .empty () : discoverNestedJarsRecursive (tempDir , jar , metadata .getJars (), parentToChildren , loadedModIds , loadedModuleNames );
121
+ LoaderModMetadata metadata = jar .modPath ().metadata ().modMetadata ();
122
+ return shouldIgnoreMod (jar , loadedModIds , loadedModuleNames ) ? Stream .empty () : discoverNestedJarsRecursive (transformer , tempDir , jar , metadata .getJars (), parentToChildren , loadedModIds , loadedModuleNames );
118
123
})
119
124
.toList ();
120
125
@@ -131,7 +136,7 @@ private List<IModFile> locateFabricMods(List<IModFile> discoveredMods) {
131
136
List <Path > renameLibs = loadedModFiles .stream ().map (modFile -> modFile .getSecureJar ().getRootPath ()).toList ();
132
137
133
138
// Run jar transformations (or get existing outputs from cache)
134
- List <JarTransformer .TransformedFabricModPath > transformed = JarTransformer .transform (candidates , renameLibs , loadedModFiles );
139
+ List <JarTransformer .TransformedFabricModPath > transformed = transformer .transform (candidates , renameLibs );
135
140
136
141
List <JarTransformer .TransformedFabricModPath > failing = transformed .stream ().filter (j -> j .auditTrail () != null && j .auditTrail ().hasFailingMixins ()).toList ();
137
142
if (!failing .isEmpty ()) {
@@ -148,7 +153,8 @@ private List<IModFile> locateFabricMods(List<IModFile> discoveredMods) {
148
153
// Deal with split packages (thanks modules)
149
154
List <SplitPackageMerger .FilteredModPath > moduleSafeJars = SplitPackageMerger .mergeSplitPackages (transformed .stream ().map (JarTransformer .TransformedFabricModPath ::output ).toList (), loadedModFiles , ignoredModFiles );
150
155
151
- return moduleSafeJars .stream ().map (ConnectorLocator ::createConnectorModFile ).toList ();
156
+ List <IModFile > loadedMods = moduleSafeJars .stream ().map (ConnectorLocator ::createConnectorModFile ).toList ();
157
+ return new LocationResult (loadedMods , environment .getGeneratedJarPath ());
152
158
}
153
159
154
160
private static IModFile createConnectorModFile (SplitPackageMerger .FilteredModPath modPath ) {
@@ -158,36 +164,36 @@ private static IModFile createConnectorModFile(SplitPackageMerger.FilteredModPat
158
164
}
159
165
ModJarMetadata modJarMetadata = new ModJarMetadata (jarContents );
160
166
SecureJar secureJar = SecureJar .from (jarContents , modJarMetadata );
161
- IModFile modFile = IModFile .create (secureJar , f -> FabricModMetadataParser .createForgeMetadata (f , modPath .metadata ().modMetadata (), modPath .metadata ().visibleMixinConfigs (), modPath .metadata ().generated ()));
167
+ IModFile modFile = IModFile .create (secureJar , f -> FabricModMetadataParser .createForgeMetadata (f , ( ConnectorFabricModMetadata ) modPath .metadata ().modMetadata (), modPath .metadata ().visibleMixinConfigs (), modPath .metadata ().generated ()));
162
168
modJarMetadata .setModFile (modFile );
163
169
return modFile ;
164
170
}
165
171
166
- private static Stream <JarTransformer .TransformableJar > discoverNestedJarsRecursive (Path tempDir , JarTransformer .TransformableJar parent , Collection <NestedJarEntry > jars , Multimap <JarTransformer .TransformableJar , JarTransformer .TransformableJar > parentToChildren , Collection <String > loadedModIds , Collection <String > loadedModuleNames ) {
172
+ private static Stream <JarTransformer .TransformableJar > discoverNestedJarsRecursive (JarTransformer transformer , Path tempDir , JarTransformer .TransformableJar parent , Collection <NestedJarEntry > jars , Multimap <JarTransformer .TransformableJar , JarTransformer .TransformableJar > parentToChildren , Collection <String > loadedModIds , Collection <String > loadedModuleNames ) {
167
173
SecureJar secureJar = SecureJar .from (parent .input ().toPath ());
168
174
return jars .stream ()
169
175
.map (entry -> secureJar .getPath (entry .getFile ()))
170
176
.filter (Files ::exists )
171
177
.flatMap (path -> {
172
- JarTransformer .TransformableJar jar = uncheck (() -> prepareNestedJar (tempDir , secureJar .getPrimaryPath ().getFileName ().toString (), path ));
178
+ JarTransformer .TransformableJar jar = uncheck (() -> prepareNestedJar (transformer , tempDir , secureJar .getPrimaryPath ().getFileName ().toString (), path ));
173
179
if (shouldIgnoreMod (jar , loadedModIds , loadedModuleNames )) {
174
180
return Stream .empty ();
175
181
}
176
182
parentToChildren .put (parent , jar );
177
- ConnectorFabricModMetadata metadata = jar .modPath ().metadata ().modMetadata ();
178
- return Stream .concat (Stream .of (jar ), discoverNestedJarsRecursive (tempDir , jar , metadata .getJars (), parentToChildren , loadedModIds , loadedModuleNames ));
183
+ LoaderModMetadata metadata = jar .modPath ().metadata ().modMetadata ();
184
+ return Stream .concat (Stream .of (jar ), discoverNestedJarsRecursive (transformer , tempDir , jar , metadata .getJars (), parentToChildren , loadedModIds , loadedModuleNames ));
179
185
});
180
186
}
181
187
182
- private static JarTransformer .TransformableJar prepareNestedJar (Path tempDir , String parentName , Path path ) throws IOException {
188
+ private static JarTransformer .TransformableJar prepareNestedJar (JarTransformer transformer , Path tempDir , String parentName , Path path ) throws IOException {
183
189
Files .createDirectories (tempDir );
184
190
185
191
String parentNameWithoutExt = parentName .split ("\\ .(?!.*\\ .)" )[0 ];
186
192
// Extract JiJ
187
193
Path extracted = tempDir .resolve (parentNameWithoutExt + "$" + path .getFileName ().toString ());
188
194
ConnectorUtil .cache (path , extracted , () -> Files .copy (path , extracted ));
189
195
190
- return uncheck (() -> JarTransformer .cacheTransformableJar (extracted .toFile ()));
196
+ return uncheck (() -> transformer .cacheTransformableJar (extracted .toFile ()));
191
197
}
192
198
193
199
// Removes any duplicates from located connector mods, as well as mods that are already located by FML.
@@ -225,7 +231,7 @@ private static List<JarTransformer.TransformableJar> handleDuplicateMods(List<Ja
225
231
}
226
232
227
233
private static boolean shouldIgnoreMod (JarTransformer .TransformableJar jar , Collection <String > loadedModIds , Collection <String > loadedModuleNames ) {
228
- ConnectorFabricModMetadata metadata = jar .modPath ().metadata ().modMetadata ();
234
+ LoaderModMetadata metadata = jar .modPath ().metadata ().modMetadata ();
229
235
String id = metadata .getId ();
230
236
return ConnectorUtil .DISABLED_MODS .contains (id ) || loadedModIds .contains (id )
231
237
|| jar .modPath ().metadata ().generated () && loadedModuleNames .contains (jar .moduleName ());
@@ -260,4 +266,6 @@ private static void loadEmbeddedJars(IDiscoveryPipeline pipeline) throws Excepti
260
266
261
267
private record SimpleModInfo (String modid , ArtifactVersion version , boolean library , @ Nullable IModFile origin , @ Nullable String moduleName ) {
262
268
}
269
+
270
+ private record LocationResult (List <IModFile > mods , Path generatedJarPath ) {}
263
271
}
0 commit comments