Skip to content

Commit d6cac34

Browse files
committed
feat: improved DepLoader UI
1 parent 33b4205 commit d6cac34

2 files changed

Lines changed: 88 additions & 53 deletions

File tree

build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ plugins {
55
group = "com.falsepattern"
66

77
//bump this after ANY change to the deploader!
8-
val deploaderVersion = 7
8+
val deploaderVersion = 8
99

1010
minecraft_fp {
1111
java {

src/deploader/java/com/falsepattern/deploader/DependencyLoaderImpl.java

Lines changed: 87 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
import javax.swing.JLabel;
4747
import javax.swing.JOptionPane;
4848
import javax.swing.JProgressBar;
49+
import javax.swing.UIManager;
4950
import javax.swing.WindowConstants;
5051
import java.awt.Dimension;
5152
import java.awt.GridBagConstraints;
@@ -76,8 +77,11 @@
7677
import java.util.concurrent.CompletableFuture;
7778
import java.util.concurrent.ConcurrentHashMap;
7879
import java.util.concurrent.ExecutorService;
79-
import java.util.concurrent.Executors;
80+
import java.util.concurrent.LinkedBlockingDeque;
81+
import java.util.concurrent.ThreadPoolExecutor;
82+
import java.util.concurrent.TimeUnit;
8083
import java.util.concurrent.atomic.AtomicBoolean;
84+
import java.util.concurrent.atomic.AtomicInteger;
8185
import java.util.concurrent.atomic.AtomicLong;
8286
import java.util.function.Consumer;
8387
import java.util.jar.JarFile;
@@ -102,11 +106,10 @@ public class DependencyLoaderImpl {
102106
private static final Set<String> localMavenRepositories = new ConcurrentSet<>();
103107
public static final Logger LOG = LogManager.getLogger("FalsePatternLib DepLoader");
104108

105-
private static final AtomicLong counter = new AtomicLong(0);
106-
private static final ExecutorService executor = Executors.newCachedThreadPool(r -> {
109+
private static final ExecutorService executor = new ThreadPoolExecutor(0, 4, 60L, TimeUnit.SECONDS, new LinkedBlockingDeque<>(), r -> {
107110
val thread = new Thread(r);
108111
thread.setDaemon(true);
109-
thread.setName("Dependency Download Thread " + counter.incrementAndGet());
112+
thread.setName("Dependency Download Thread");
110113
return thread;
111114
});
112115
private static final Path libDir;
@@ -752,30 +755,38 @@ static ScopeSide current() {
752755
LOG.info("-----------------------------------------------------------");
753756
}
754757
JFrame theFrame = null;
755-
val progresses = new HashMap<DependencyLoadTask, JProgressBar>();
758+
JProgressBar bar = null;
759+
JProgressBar subBar = null;
756760
if (silent) {
757761

758762
} else if (SystemUtils.IS_OS_MAC) {
759763
LOG.info("MacOS detected, not creating progress window (your OS is buggy)");
760764
} else {
761765
try {
766+
try {
767+
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
768+
} catch (Throwable ignored) {}
762769
val jFrame = new JFrame("Dependency Download");
763770
val constraints = new GridBagConstraints();
764771
jFrame.getContentPane().setLayout(new GridBagLayout());
765772
constraints.gridy = 0;
766-
constraints.gridwidth = 2;
767-
jFrame.add(new JLabel("FalsePatternLib is downloading dependencies, please wait!"), constraints);
773+
constraints.gridx = 0;
768774
constraints.gridwidth = 1;
769-
for (val artifact : artifactMap.entrySet()) {
770-
constraints.gridy++;
771-
jFrame.add(new JLabel(artifact.getKey()), constraints);
772-
val status = new JProgressBar();
773-
status.setIndeterminate(true);
774-
status.setStringPainted(true);
775-
status.setString("Waiting...");
776-
progresses.put(artifact.getValue(), status);
777-
jFrame.add(status, constraints);
778-
}
775+
constraints.gridheight = 1;
776+
constraints.fill = GridBagConstraints.HORIZONTAL;
777+
jFrame.add(new JLabel("Downloading additional jar files required by the modpack, please wait..."), constraints);
778+
constraints.gridy++;
779+
bar = new JProgressBar();
780+
bar.setIndeterminate(true);
781+
bar.setStringPainted(true);
782+
bar.setString("Waiting...");
783+
jFrame.add(bar, constraints);
784+
constraints.gridy++;
785+
subBar = new JProgressBar();
786+
subBar.setIndeterminate(true);
787+
subBar.setStringPainted(true);
788+
subBar.setString("...");
789+
jFrame.add(subBar, constraints);
779790
jFrame.pack();
780791
jFrame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
781792
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
@@ -784,27 +795,12 @@ static ScopeSide current() {
784795
} catch (Exception ignored) {
785796
}
786797
}
787-
if (theFrame != null) {
788-
for (val task : artifactMap.values()) {
789-
futures.add(CompletableFuture.supplyAsync(() -> {
790-
val bar = progresses.get(task);
791-
bar.setString("Downloading...");
792-
val res = task.load();
793-
bar.setMinimum(0);
794-
bar.setMaximum(1);
795-
bar.setValue(1);
796-
bar.setString("Completed!");
797-
return res;
798-
}, executor));
799-
}
800-
} else {
801-
for (val task : artifactMap.values()) {
802-
futures.add(CompletableFuture.supplyAsync(task::load, executor));
803-
}
798+
for (val task : artifactMap.values()) {
799+
futures.add(CompletableFuture.supplyAsync(task::load, executor));
804800
}
805801
AtomicBoolean doViz = new AtomicBoolean(true);
806802
if (theFrame != null) {
807-
final var vizThread = getVizThread(doViz, progresses, theFrame);
803+
final var vizThread = getVizThread(doViz, artifactMap, bar, subBar, theFrame);
808804
vizThread.start();
809805
}
810806
List<URL> res = new ArrayList<>();
@@ -852,7 +848,7 @@ static ScopeSide current() {
852848
}
853849

854850
@NotNull
855-
private static Thread getVizThread(AtomicBoolean doViz, HashMap<DependencyLoadTask, JProgressBar> progresses, JFrame theFrame) {
851+
private static Thread getVizThread(AtomicBoolean doViz, Map<String, DependencyLoadTask> progresses, JProgressBar mainProgress, JProgressBar subProgress, JFrame theFrame) {
856852
val vizThread = new Thread(() -> {
857853
int waitBeforeShowing = 100;
858854
while (doViz.get()) {
@@ -862,19 +858,50 @@ private static Thread getVizThread(AtomicBoolean doViz, HashMap<DependencyLoadTa
862858
theFrame.setVisible(true);
863859
waitBeforeShowing = -1;
864860
}
865-
for (val progress : progresses.entrySet()) {
866-
val task = progress.getKey();
867-
val bar = progress.getValue();
868-
if (task.contentLength == -1) {
869-
bar.setIndeterminate(true);
870-
} else {
871-
bar.setIndeterminate(false);
872-
bar.setMinimum(0);
873-
bar.setMaximum((int) task.contentLength);
874-
bar.setValue((int) task.downloaded);
861+
mainProgress.setIndeterminate(false);
862+
mainProgress.setMaximum(0);
863+
mainProgress.setMaximum(progresses.size() * 100);
864+
var currentProgress = 0;
865+
var pending = progresses.size();
866+
boolean first = true;
867+
for (val pair: progresses.entrySet()) {
868+
val progress = pair.getValue();
869+
val dls = progress.dlState.get();
870+
val cl = progress.contentLength.get();
871+
val dl = progress.downloaded.get();
872+
switch (dls) {
873+
case 0: break;
874+
case 1: {
875+
var div = cl == -1 ? dl : cl;
876+
if (div <= 0) {
877+
div = 1;
878+
}
879+
val prog = (int) Math.max(0, Math.min(100, dl * 100 / div));
880+
currentProgress += prog;
881+
if (first) {
882+
first = false;
883+
subProgress.setIndeterminate(false);
884+
subProgress.setString(pair.getKey());
885+
subProgress.setMinimum(0);
886+
subProgress.setMaximum(100);
887+
subProgress.setValue(prog);
888+
}
889+
break;
890+
}
891+
default: {
892+
currentProgress += 100;
893+
pending--;
894+
}
875895
}
876896
}
877-
theFrame.repaint();
897+
if (first) {
898+
subProgress.setIndeterminate(true);
899+
subProgress.setString("...");
900+
}
901+
mainProgress.setString(pending + " files remaining...");
902+
mainProgress.setValue(currentProgress);
903+
mainProgress.repaint();
904+
subProgress.repaint();
878905
try {
879906
Thread.sleep(10);
880907
} catch (InterruptedException ignored) {
@@ -941,34 +968,40 @@ private static class DependencyLoadTask {
941968
public volatile String jarName;
942969
private Path file;
943970

944-
public volatile long contentLength = -1;
945-
public volatile long downloaded = 0;
971+
public final AtomicLong contentLength = new AtomicLong(-1);
972+
public final AtomicLong downloaded = new AtomicLong(0);
973+
public final AtomicInteger dlState = new AtomicInteger(0);
946974

947975
private @Nullable URL load() {
948976
setupLibraryNames();
949977
if (loadedLibraries.containsKey(artifact)) {
950978
alreadyLoaded(false);
979+
dlState.set(3);
951980
return null;
952981
}
953982
if (isMod && loadedModIds.containsKey(modId)) {
954983
alreadyLoaded(true);
984+
dlState.set(3);
955985
return null;
956986
}
957987
setupPaths();
958988
for (val repo: localMavenRepositories) {
959989
val url = tryDownloadFromMaven(repo, true);
960990
if (url != null) {
991+
dlState.set(3);
961992
return url;
962993
}
963994
}
964995
val existingUrl = tryLoadingExistingFile();
965996
if (existingUrl != null) {
997+
dlState.set(3);
966998
return existingUrl;
967999
}
9681000
validateDownloadsAllowed();
9691001
for (var repo : remoteMavenRepositories) {
9701002
val url = tryDownloadFromMaven(repo, false);
9711003
if (url != null) {
1004+
dlState.set(3);
9721005
return url;
9731006
}
9741007
}
@@ -1121,18 +1154,18 @@ private void validateDownloadsAllowed() {
11211154
if (Files.exists(tmpFile)) {
11221155
Files.delete(tmpFile);
11231156
}
1157+
dlState.set(1);
11241158
Internet.connect(new URL(url),
11251159
ex -> LOG.debug("Artifact {} could not be downloaded from repo {}: {}",
11261160
artifactLogName,
11271161
finalRepo,
11281162
ex.getMessage()),
11291163
input -> {
11301164
LOG.debug("Downloading {} from {}", artifactLogName, finalRepo);
1131-
download(input, tmpFile, d -> downloaded += d);
1165+
download(input, tmpFile, downloaded::getAndAdd);
11321166
LOG.debug("Downloaded {} from {}", artifactLogName, finalRepo);
11331167
success.set(true);
1134-
},
1135-
contentLength -> this.contentLength = contentLength);
1168+
}, this.contentLength::getAndAdd);
11361169
if (success.get()) {
11371170
if (FileUtils.contentEquals(tmpFile.toFile(), file.toFile())) {
11381171
Files.delete(tmpFile);
@@ -1171,11 +1204,13 @@ private void validateDownloadsAllowed() {
11711204
loadedModIds.put(modId, preferredVersion);
11721205
loadedModIdMods.put(modId, loadingModId);
11731206
}
1207+
dlState.set(2);
11741208
return diskUrl;
11751209
}
11761210
}
11771211
} catch (IOException ignored) {
11781212
}
1213+
dlState.set(2);
11791214
return null;
11801215
}
11811216
}

0 commit comments

Comments
 (0)