3939import org .jetbrains .annotations .NotNull ;
4040import org .jetbrains .annotations .Nullable ;
4141
42+ import cpw .mods .fml .common .MetadataCollection ;
43+ import cpw .mods .fml .common .ModMetadata ;
44+
4245import javax .swing .JFrame ;
4346import javax .swing .JLabel ;
4447import javax .swing .JOptionPane ;
5356import java .io .IOException ;
5457import java .io .InputStream ;
5558import java .io .InputStreamReader ;
59+ import java .lang .reflect .Field ;
5660import java .net .MalformedURLException ;
5761import java .net .URISyntaxException ;
5862import java .net .URL ;
@@ -92,6 +96,8 @@ public class DependencyLoaderImpl {
9296 private static final Set <Path > alreadyScannedSources = new ConcurrentSet <>();
9397 private static final Map <String , Version > loadedLibraries = new ConcurrentHashMap <>();
9498 private static final Map <String , String > loadedLibraryMods = new ConcurrentHashMap <>();
99+ private static final Map <String , Version > loadedModIds = new ConcurrentHashMap <>();
100+ private static final Map <String , String > loadedModIdMods = new ConcurrentHashMap <>();
95101 private static final Set <String > remoteMavenRepositories = new ConcurrentSet <>();
96102 private static final Set <String > localMavenRepositories = new ConcurrentSet <>();
97103 static final Logger LOG = LogManager .getLogger ("FalsePatternLib DepLoader" );
@@ -106,6 +112,16 @@ public class DependencyLoaderImpl {
106112 private static final Path libDir ;
107113 private static final Path modsDir ;
108114 private static final Path tempDir ;
115+ private static final Field metadataCollectionModListAccessor ;
116+
117+ static {
118+ try {
119+ metadataCollectionModListAccessor = MetadataCollection .class .getDeclaredField ("modList" );
120+ } catch (NoSuchFieldException e ) {
121+ throw new RuntimeException (e );
122+ }
123+ metadataCollectionModListAccessor .setAccessible (true );
124+ }
109125
110126 private static AtomicBoolean modDownloaded = new AtomicBoolean (false );
111127
@@ -260,7 +276,8 @@ public static CompletableFuture<Void> loadLibrariesAsync(Library... libraries) {
260276 library .preferredVersion ,
261277 library .regularSuffix ,
262278 library .devSuffix ,
263- false );
279+ false ,
280+ null );
264281 futures .add (CompletableFuture .supplyAsync (task ::load , executor ));
265282 }
266283 return CompletableFuture .allOf (futures .toArray (new CompletableFuture [0 ])).thenAccept (ignored -> {
@@ -274,6 +291,26 @@ public static CompletableFuture<Void> loadLibrariesAsync(Library... libraries) {
274291 });
275292 }
276293
294+ @ SneakyThrows
295+ private static void readMCMod (InputStream input , String name ) {
296+ val meta = MetadataCollection .from (input , name );
297+ val modList = (ModMetadata [])metadataCollectionModListAccessor .get (meta );
298+ for (val mod : modList ) {
299+ val id = mod .modId ;
300+ if (id != null ) {
301+ val versionStr = mod .version ;
302+ final Version version ;
303+ if (versionStr != null ) {
304+ version = Version .parse (versionStr );
305+ } else {
306+ version = new RawVersion ("unknown" );
307+ }
308+ loadedModIds .put (id , version );
309+ loadedModIdMods .put (id , name );
310+ }
311+ }
312+ }
313+
277314 private static boolean scanForDepSpecs (URL source , List <URL > output , List <URL > jijURLs ) {
278315 if (!source .getProtocol ().equals ("file" )) {
279316 return false ;
@@ -298,6 +335,9 @@ private static boolean scanForDepSpecs(URL source, List<URL> output, List<URL> j
298335 ZipEntry entry ;
299336 while ((entry = jarFile .getNextEntry ()) != null ) {
300337 val name = entry .getName ();
338+ if (name .equals ("mcmod.info" )) {
339+ readMCMod (jarFile , source .toString ());
340+ }
301341 if (!name .startsWith ("META-INF/" ))
302342 continue ;
303343 if (name .endsWith (".json" ) && name .matches ("META-INF/\\ w+.json" )) {
@@ -430,7 +470,12 @@ public static void executeDependencyLoading() {
430470 JOptionPane .showMessageDialog (null , "A minecraft mod has been downloaded by the FalsePatternLib dependency downloader.\n You must restart the game to apply these changes." , "Mod Dependency Download notice" , JOptionPane .WARNING_MESSAGE );
431471 } catch (Exception ignored ) {}
432472 }
433- throw new ModDependencyDownloaded ("A minecraft mod has been downloaded by the FalsePatternLib dependency downloader, and requires a game restart to get installed properly." );
473+ val msg = "A minecraft mod has been downloaded by the FalsePatternLib dependency downloader, and requires a game restart to get installed properly." ;
474+ for (int i = 0 ; i < 16 ; i ++) {
475+ LOG .warn (msg );
476+ }
477+ System .exit (0 );
478+ throw new ModDependencyDownloaded (msg );
434479 }
435480 }
436481
@@ -495,6 +540,7 @@ public ModDependencyDownloaded(String message) {
495540 }
496541 val builder = new GsonBuilder ();
497542 builder .excludeFieldsWithoutExposeAnnotation ();
543+ builder .registerTypeAdapterFactory (new DepRoot .Dependency .Adapter .Factory ());
498544 val gson = builder .create ();
499545 json .remove ("identifier" );
500546 val root = gson .fromJson (json , DepRoot .class );
@@ -524,8 +570,8 @@ public ModDependencyDownloaded(String message) {
524570 if (bundled == null ) {
525571 continue ;
526572 }
527- for (String artifact : bundled ) {
528- val parts = artifact .split (":" );
573+ for (var dep : bundled ) {
574+ val parts = dep . artifact () .split (":" );
529575 if (parts .length < 3 ) {
530576 LOG .error ("Invalid bundled artifact: {}" , dependencySpec );
531577 continue ;
@@ -549,11 +595,22 @@ public ModDependencyDownloaded(String message) {
549595 dependencySpec .source ());
550596 }
551597 val id = groupId + ":" + artifactId + ":" + classifier ;
598+ val src = dependencySpec .source ();
552599 if (!loadedLibraries .containsKey (id )) {
553600 loadedLibraries .put (id , version );
554601 }
555602 if (!loadedLibraryMods .containsKey (id )) {
556- loadedLibraryMods .put (id , dependencySpec .source ());
603+ loadedLibraryMods .put (id , src );
604+ }
605+ val modid = dep .modid ();
606+ if (modid != null ) {
607+ LOG .info ("With modid: {}" , modid );
608+ if (!loadedModIds .containsKey (modid )) {
609+ loadedModIds .put (modid , version );
610+ }
611+ if (!loadedModIdMods .containsKey (modid )) {
612+ loadedModIdMods .put (modid , src );
613+ }
557614 }
558615 }
559616 }
@@ -578,7 +635,7 @@ public ModDependencyDownloaded(String message) {
578635 val source = scopedSidedDep .source ;
579636 val scope = scopedSidedDep .scope ;
580637 val dep = scopedSidedDep .dep ;
581- val parts = dep .split (":" );
638+ val parts = dep .artifact (). split (":" );
582639 if (parts .length < 3 ) {
583640 LOG .error ("Invalid dependency: {}" , dep );
584641 return null ;
@@ -610,7 +667,8 @@ public ModDependencyDownloaded(String message) {
610667 version ,
611668 classifier ,
612669 classifier ,
613- scopedSidedDep .mod ));
670+ scopedSidedDep .mod ,
671+ dep .modid ()));
614672 })
615673 .filter (Objects ::nonNull )
616674 .collect (Collectors .toSet ());
@@ -620,7 +678,7 @@ public ModDependencyDownloaded(String message) {
620678 return artifacts ;
621679 }
622680
623- private static Stream <ScopedSidedDep > concat (ScopedDep it , @ Nullable Stream <ScopedSidedDep > prev , List <String > deps , DependencySide side ) {
681+ private static Stream <ScopedSidedDep > concat (ScopedDep it , @ Nullable Stream <ScopedSidedDep > prev , List <DepRoot . Dependency > deps , DependencySide side ) {
624682 if (deps != null ) {
625683 val newStream = deps .stream ().map (dep -> new ScopedSidedDep (it .source , it .mod , new ScopeSide (it .scope , side ), dep ));
626684 if (prev == null ) {
@@ -826,7 +884,7 @@ private static class ScopedSidedDep {
826884 public final String source ;
827885 public final boolean mod ;
828886 public final ScopeSide scope ;
829- public final String dep ;
887+ public final DepRoot . Dependency dep ;
830888 }
831889
832890 @ RequiredArgsConstructor
@@ -851,6 +909,7 @@ private static class DependencyLoadTask {
851909 private final String regularSuffix ;
852910 private final String devSuffix ;
853911 private final boolean isMod ;
912+ private final String modId ;
854913
855914 private String suffix ;
856915 private String artifactLogName ;
@@ -865,7 +924,11 @@ private static class DependencyLoadTask {
865924 private @ Nullable URL load () {
866925 setupLibraryNames ();
867926 if (loadedLibraries .containsKey (artifact )) {
868- alreadyLoaded ();
927+ alreadyLoaded (false );
928+ return null ;
929+ }
930+ if (isMod && loadedModIds .containsKey (modId )) {
931+ alreadyLoaded (true );
869932 return null ;
870933 }
871934 setupPaths ();
@@ -909,14 +972,14 @@ private void setupLibraryNames() {
909972 artifact = groupId + ":" + artifactId + ":" + suffix ;
910973 }
911974
912- private void alreadyLoaded () {
913- val currentVer = loadedLibraries .get (artifact );
975+ private void alreadyLoaded (boolean fromModId ) {
976+ val currentVer = fromModId ? loadedModIds . get ( modId ) : loadedLibraries .get (artifact );
914977 if (currentVer .equals (preferredVersion )) {
915978 return ;
916979 }
917980 val rangeString = "(minimum: " + minVersion + (maxVersion == null ? "" : ", maximum: " + maxVersion ) + ")" ;
918981 if (minVersion .compareTo (currentVer ) > 0 || (maxVersion != null && maxVersion .compareTo (currentVer ) < 0 )) {
919- for (int i = 0 ; i < 16 ; i ++) {
982+ for (int i = 0 ; i < 4 ; i ++) {
920983 LOG .fatal ("ALERT VVVVVVVVVVVV ALERT" );
921984 }
922985 LOG .fatal ("Library {}:{}{} already loaded with version {}, "
@@ -928,8 +991,8 @@ private void alreadyLoaded() {
928991 currentVer ,
929992 rangeString ,
930993 loadingModId ,
931- loadedLibraryMods .get (artifact ));
932- for (int i = 0 ; i < 16 ; i ++) {
994+ fromModId ? loadedModIdMods . get ( modId ) : loadedLibraryMods .get (artifact ));
995+ for (int i = 0 ; i < 4 ; i ++) {
933996 LOG .fatal ("ALERT ^^^^^^^^^^^^ ALERT" );
934997 }
935998 } else {
@@ -944,7 +1007,7 @@ private void alreadyLoaded() {
9441007 currentVer ,
9451008 rangeString ,
9461009 loadingModId ,
947- loadedLibraryMods .get (artifact ));
1010+ fromModId ? loadedModIdMods . get ( modId ) : loadedLibraryMods .get (artifact ));
9481011 }
9491012 }
9501013
@@ -978,6 +1041,9 @@ private void setupPaths() {
9781041 addToClasspath (theUrl );
9791042 }
9801043 loadedLibraries .put (artifact , preferredVersion );
1044+ if (isMod && modId != null ) {
1045+ loadedModIds .put (modId , preferredVersion );
1046+ }
9811047 LOG .debug ("Library {} successfully loaded from disk!" , artifactLogName );
9821048 return theUrl ;
9831049 } catch (Exception e ) {
@@ -1075,6 +1141,10 @@ private void validateDownloadsAllowed() {
10751141 if (!isMod ) {
10761142 addToClasspath (diskUrl );
10771143 }
1144+ if (isMod && modId != null ) {
1145+ loadedModIds .put (modId , preferredVersion );
1146+ loadedModIdMods .put (modId , loadingModId );
1147+ }
10781148 return diskUrl ;
10791149 }
10801150 }
0 commit comments