diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListPage.java index 487187889..304eafaa9 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/WorldListPage.java @@ -50,8 +50,13 @@ public class WorldListPage extends ListPage { public void loadVersion(Profile profile, String id) { this.savesDir = profile.getRepository().getRunDirectory(id).toPath().resolve("saves"); - itemsProperty().setAll(World.getWorlds(savesDir).stream() - .map(WorldListItem::new).collect(Collectors.toList())); + setLoading(true); + Task.ofResult(() -> World.getWorlds(savesDir).parallel().collect(Collectors.toList())) + .finalizedResult(Schedulers.javafx(), (result, isDependentsSucceeded) -> { + setLoading(false); + if (isDependentsSucceeded) + itemsProperty().setAll(result.stream().map(WorldListItem::new).collect(Collectors.toList())); + }).start(); } @Override @@ -65,28 +70,26 @@ public class WorldListPage extends ListPage { installWorld(res.get(0)); } - public void installWorld(File zipFile) { - try { - // Only accept one world file because user is required to confirm the new world name - // Or too many input dialogs are popped. - World world = new World(zipFile.toPath()); - - Controllers.inputDialog(i18n("world.name.enter"), (name, resolve, reject) -> { - Task.of(() -> world.install(savesDir, name)) - .finalized(Schedulers.javafx(), var -> { - itemsProperty().add(new WorldListItem(new World(savesDir.resolve(name)))); - resolve.run(); - }, e -> { - if (e instanceof FileAlreadyExistsException) - reject.accept(i18n("world.import.failed", i18n("world.import.already_exists"))); - else - reject.accept(i18n("world.import.failed", e.getClass().getName() + ": " + e.getLocalizedMessage())); - }).start(); - }).setInitialText(world.getWorldName()); - - } catch (IOException | IllegalArgumentException e) { - Logging.LOG.log(Level.WARNING, "Unable to parse world file " + zipFile, e); - Controllers.dialog(i18n("world.import.invalid")); - } + private void installWorld(File zipFile) { + // Only accept one world file because user is required to confirm the new world name + // Or too many input dialogs are popped. + Task.ofResult(() -> new World(zipFile.toPath())) + .finalizedResult(Schedulers.javafx(), world -> { + Controllers.inputDialog(i18n("world.name.enter"), (name, resolve, reject) -> { + Task.of(() -> world.install(savesDir, name)) + .finalized(Schedulers.javafx(), var -> { + itemsProperty().add(new WorldListItem(new World(savesDir.resolve(name)))); + resolve.run(); + }, e -> { + if (e instanceof FileAlreadyExistsException) + reject.accept(i18n("world.import.failed", i18n("world.import.already_exists"))); + else + reject.accept(i18n("world.import.failed", e.getClass().getName() + ": " + e.getLocalizedMessage())); + }).start(); + }).setInitialText(world.getWorldName()); + }, e -> { + Logging.LOG.log(Level.WARNING, "Unable to parse world file " + zipFile, e); + Controllers.dialog(i18n("world.import.invalid")); + }).start(); } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/World.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/World.java index d63d9fc8d..67731635d 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/World.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/World.java @@ -39,6 +39,7 @@ import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import java.util.stream.Collectors; +import java.util.stream.Stream; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; @@ -202,20 +203,20 @@ public class World { } } - public static List getWorlds(Path savesDir) { - List worlds = new ArrayList<>(); + public static Stream getWorlds(Path savesDir) { try { if (Files.exists(savesDir)) - for (Path world : Files.newDirectoryStream(savesDir)) { + return Files.list(savesDir).flatMap(world -> { try { - worlds.add(new World(world)); + return Stream.of(new World(world)); } catch (IOException | IllegalArgumentException e) { Logging.LOG.log(Level.WARNING, "Failed to read world " + world, e); + return Stream.empty(); } - } + }); } catch (IOException e) { Logging.LOG.log(Level.WARNING, "Failed to read saves", e); } - return worlds; + return Stream.empty(); } }