2626
2727import com .google .gson .Gson ;
2828import com .google .gson .stream .JsonReader ;
29- import net .minecraftforge .fart .api .Renamer ;
30- import net .minecraftforge .fart .api .SignatureStripperConfig ;
31- import net .minecraftforge .fart .api .SourceFixerConfig ;
32- import net .minecraftforge .fart .api .Transformer ;
33- import net .minecraftforge .srgutils .IMappingFile ;
3429import org .spongepowered .bootstrap .forge .VanillaBootstrap ;
3530import org .spongepowered .libs .LibraryManager ;
3631import org .spongepowered .libs .LibraryUtils ;
5045import java .net .URI ;
5146import java .net .URL ;
5247import java .net .URLConnection ;
53- import java .nio .file .AccessDeniedException ;
5448import java .nio .file .FileSystem ;
5549import java .nio .file .FileSystems ;
5650import java .nio .file .Files ;
5751import java .nio .file .Path ;
58- import java .nio .file .StandardCopyOption ;
5952import java .security .NoSuchAlgorithmException ;
6053import java .util .ArrayList ;
61- import java .util .Collection ;
6254import java .util .Collections ;
6355import java .util .HashMap ;
6456import java .util .HashSet ;
@@ -77,7 +69,6 @@ public final class InstallerMain {
7769
7870 private static final String COLLECTION_BOOTSTRAP = "bootstrap" ; // boot layer
7971 private static final String COLLECTION_MAIN = "main" ; // game layer
80- private static final int MAX_TRIES = 2 ;
8172
8273 private final Installer installer ;
8374 private final boolean isolated ;
@@ -104,35 +95,32 @@ public void run() throws Exception {
10495 }
10596
10697 private void downloadAndRun () throws Exception {
107- ServerAndLibraries remappedMinecraftJar = null ;
98+ ServerAndLibraries extractedMinecraftJar = null ;
10899 Version mcVersion = null ;
109100 try {
110101 mcVersion = this .downloadMinecraftManifest ();
111102 } catch (final IOException ex ) {
112- remappedMinecraftJar = this .recoverFromMinecraftDownloadError (ex );
103+ extractedMinecraftJar = this .recoverFromMinecraftDownloadError (ex );
113104 }
114105
115106 final LibraryManager libraryManager = this .installer .getLibraryManager ();
116107 try {
117108 if (mcVersion != null ) {
118- final CompletableFuture <Path > originalMcFuture = this .downloadMinecraft (mcVersion );
119- final CompletableFuture <ServerAndLibraries > extractedFuture = originalMcFuture
120- .thenApplyAsync (this ::extractBundle , libraryManager .preparationWorker ());
121- remappedMinecraftJar = extractedFuture .get ();
109+ extractedMinecraftJar = this .downloadMinecraft (mcVersion ).thenApplyAsync (this ::extractBundle , libraryManager .preparationWorker ()).get ();
122110 }
123111 } catch (final ExecutionException ex ) {
124112 final /* @Nullable */ Throwable cause = ex .getCause ();
125- remappedMinecraftJar = this .recoverFromMinecraftDownloadError (cause instanceof Exception ? (Exception ) cause : ex );
113+ extractedMinecraftJar = this .recoverFromMinecraftDownloadError (cause instanceof Exception ? (Exception ) cause : ex );
126114 }
127- assert remappedMinecraftJar != null ; // always assigned or thrown
115+ assert extractedMinecraftJar != null ; // always assigned or thrown
128116
129117 libraryManager .validate ();
130118
131119 // Minecraft itself is on the main layer
132- libraryManager .addLibrary (InstallerMain .COLLECTION_MAIN , new LibraryManager .Library ("minecraft" , remappedMinecraftJar .server ()));
120+ libraryManager .addLibrary (InstallerMain .COLLECTION_MAIN , new LibraryManager .Library ("minecraft" , extractedMinecraftJar .server ()));
133121
134122 // Other libs are on the bootstrap layer
135- for (final Map .Entry <GroupArtifactVersion , Path > entry : remappedMinecraftJar .libraries ().entrySet ()) {
123+ for (final Map .Entry <GroupArtifactVersion , Path > entry : extractedMinecraftJar .libraries ().entrySet ()) {
136124 final GroupArtifactVersion artifact = entry .getKey ();
137125 final Path path = entry .getValue ();
138126
@@ -211,10 +199,9 @@ private static Path newJarInJar(final Path jar) {
211199
212200 private <T extends Throwable > ServerAndLibraries recoverFromMinecraftDownloadError (final T ex ) throws T {
213201 final Path expectedUnpacked = this .expectedMinecraftLocation (Constants .Libraries .MINECRAFT_VERSION_TARGET );
214- final Path expectedRemapped = this .expectedRemappedLocation (expectedUnpacked );
215202 // Re-read bundler metadata (needs original bundled location)
216- if (Files .exists (expectedRemapped )) {
217- Logger .warn (ex , "Failed to download and remap Minecraft. An existing jar exists, so we will attempt to use that instead." );
203+ if (Files .exists (expectedUnpacked )) {
204+ Logger .warn (ex , "Failed to download Minecraft. An existing jar exists, so we will attempt to use that instead." );
218205 return this .extractBundle (this .expectedBundleLocation (expectedUnpacked ));
219206 } else {
220207 throw ex ;
@@ -276,10 +263,6 @@ private Path expectedMinecraftLocation(final String version) {
276263 .resolve (Constants .Libraries .MINECRAFT_SERVER_JAR_NAME + ".jar" );
277264 }
278265
279- private Path expectedRemappedLocation (final Path originalLocation ) {
280- return originalLocation .resolveSibling (Constants .Libraries .MINECRAFT_SERVER_JAR_NAME + "-remapped.jar" );
281- }
282-
283266 private Path expectedBundleLocation (final Path originalLocation ) {
284267 return originalLocation .resolveSibling (Constants .Libraries .MINECRAFT_SERVER_JAR_NAME + "-bundle.jar" );
285268 }
@@ -372,137 +355,9 @@ private ServerAndLibraries extractBundle(final Path bundleJar) {
372355 }
373356 }
374357
375- private CompletableFuture <Path > downloadMappings (final Version version ) {
376- return LibraryUtils .asyncFailableFuture (() -> {
377- Logger .info ("Setting up names for Minecraft {}" , Constants .Libraries .MINECRAFT_VERSION_TARGET );
378- final Path downloadTarget = this .installer .getLibraryManager ().getRootDirectory ().resolve (Constants .Libraries .MINECRAFT_MAPPINGS_PREFIX )
379- .resolve (Constants .Libraries .MINECRAFT_VERSION_TARGET )
380- .resolve (Constants .Libraries .MINECRAFT_MAPPINGS_NAME );
381-
382- final Version .Downloads .Download mappings = version .downloads ().server_mappings ();
383- if (mappings == null ) {
384- throw new IOException (String .format ("Mappings were not included in version manifest for %s" , Constants .Libraries .MINECRAFT_VERSION_TARGET ));
385- }
386-
387- final boolean checkHashes = this .installer .getConfig ().checkLibraryHashes ();
388- if (Files .exists (downloadTarget )) {
389- if (checkHashes ) {
390- Logger .info ("Detected existing mappings, verifying hashes..." );
391- if (LibraryUtils .validateDigest ("SHA-1" , mappings .sha1 (), downloadTarget )) {
392- Logger .info ("Mappings verified!" );
393- return downloadTarget ;
394- } else {
395- Logger .error ("Checksum verification failed: Expected {}. Deleting cached server mappings file..." , mappings .sha1 ());
396- Files .delete (downloadTarget );
397- }
398- } else {
399- return downloadTarget ;
400- }
401- }
402-
403- if (this .installer .getConfig ().autoDownloadLibraries ()) {
404- if (checkHashes ) {
405- LibraryUtils .downloadAndVerifyDigest (TinyLogger .INSTANCE , mappings .url (), downloadTarget , "SHA-1" , mappings .sha1 ());
406- } else {
407- LibraryUtils .download (TinyLogger .INSTANCE , mappings .url (), downloadTarget , false );
408- }
409- } else {
410- throw new IOException (String .format ("Mappings were not located at '%s' and downloading them has been turned off." , downloadTarget ));
411- }
412-
413- return downloadTarget ;
414- }, this .installer .getLibraryManager ().preparationWorker ());
415- }
416-
417- private ServerAndLibraries remapMinecraft (final ServerAndLibraries minecraft , final Path serverMappings ) throws IOException {
418- Logger .info ("Checking if we need to remap Minecraft..." );
419- final Path outputJar = this .expectedRemappedLocation (minecraft .server ());
420- final Path tempOutput = outputJar .resolveSibling (Constants .Libraries .MINECRAFT_SERVER_JAR_NAME + "_remapped.jar.tmp" );
421-
422- if (Files .exists (outputJar )) {
423- Logger .info ("Remapped Minecraft detected, skipping..." );
424- return minecraft .server (outputJar );
425- }
426-
427- Logger .info ("Remapping Minecraft. This may take a while..." );
428- final IMappingFile mappings = IMappingFile .load (serverMappings .toFile ()).reverse ();
429-
430- final Renamer .Builder renamerBuilder = Renamer .builder ()
431- .add (Transformer .parameterAnnotationFixerFactory ())
432- .add (ctx -> {
433- final Transformer backing = Transformer .renamerFactory (mappings , false ).create (ctx );
434- return new Transformer () {
435- @ Override
436- public ClassEntry process (final ClassEntry entry ) {
437- final String name = entry .getName ();
438- if (name .startsWith ("it/unimi" )
439- || name .startsWith ("com/google" )
440- || name .startsWith ("com/mojang/datafixers" )
441- || name .startsWith ("com/mojang/brigadier" )
442- || name .startsWith ("org/apache" )) {
443- return entry ;
444- }
445- return backing .process (entry );
446- }
447-
448- @ Override
449- public ManifestEntry process (final ManifestEntry entry ) {
450- return backing .process (entry );
451- }
452-
453- @ Override
454- public ResourceEntry process (final ResourceEntry entry ) {
455- return backing .process (entry );
456- }
457-
458- @ Override
459- public Collection <? extends Entry > getExtras () {
460- return backing .getExtras ();
461- }
462- };
463- })
464- .add (Transformer .recordFixerFactory ())
465- .add (Transformer .parameterAnnotationFixerFactory ())
466- .add (Transformer .sourceFixerFactory (SourceFixerConfig .JAVA ))
467- .add (Transformer .signatureStripperFactory (SignatureStripperConfig .ALL ))
468- .logger (Logger ::debug ); // quiet
469-
470- try (final Renamer ren = renamerBuilder .build ()) {
471- ren .run (minecraft .server .toFile (), tempOutput .toFile ());
472- }
473-
474- // Restore file
475- try {
476- Files .move (tempOutput , outputJar , StandardCopyOption .ATOMIC_MOVE , StandardCopyOption .REPLACE_EXISTING );
477- } catch (final AccessDeniedException ex ) {
478- // Sometimes because of file locking this will fail... Let's just try again and hope for the best
479- // Thanks Windows!
480- for (int tries = 0 ; tries < InstallerMain .MAX_TRIES ; ++tries ) {
481- // Pause for a bit
482- try {
483- Thread .sleep (5 * tries );
484- Files .move (tempOutput , outputJar , StandardCopyOption .ATOMIC_MOVE , StandardCopyOption .REPLACE_EXISTING );
485- } catch (final AccessDeniedException ex2 ) {
486- if (tries == InstallerMain .MAX_TRIES - 1 ) {
487- throw ex ;
488- }
489- } catch (final InterruptedException exInterrupt ) {
490- Thread .currentThread ().interrupt ();
491- throw ex ;
492- }
493- }
494- }
495-
496- return minecraft .server (outputJar );
497- }
498-
499358 record ServerAndLibraries (Path server , Map <GroupArtifactVersion , Path > libraries ) {
500359 ServerAndLibraries {
501360 libraries = Map .copyOf (libraries );
502361 }
503-
504- public ServerAndLibraries server (final Path server ) {
505- return new ServerAndLibraries (server , this .libraries );
506- }
507362 }
508363}
0 commit comments