Skip to content

Commit

Permalink
Implement optional mods and cancel buttons
Browse files Browse the repository at this point in the history
  • Loading branch information
comp500 committed Aug 11, 2019
1 parent 5a54a90 commit 7946377
Show file tree
Hide file tree
Showing 8 changed files with 182 additions and 36 deletions.
9 changes: 6 additions & 3 deletions src/main/java/link/infra/packwiz/installer/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,19 @@
import link.infra.packwiz.installer.metadata.SpaceSafeURI;
import link.infra.packwiz.installer.ui.CLIHandler;
import link.infra.packwiz.installer.ui.IUserInterface;
import link.infra.packwiz.installer.ui.InputStateHandler;
import link.infra.packwiz.installer.ui.InstallWindow;
import org.apache.commons.cli.*;

import javax.swing.*;
import java.awt.*;
import java.net.URISyntaxException;

@SuppressWarnings("unused")
public class Main {

// Actual main() is in RequiresBootstrap!

@SuppressWarnings("unused")
public Main(String[] args) {
// Big overarching try/catch just in case everything breaks
try {
Expand Down Expand Up @@ -79,7 +81,8 @@ private void startup(String[] args) {
ui.setTitle(title);
}

ui.show();
InputStateHandler inputStateHandler = new InputStateHandler();
ui.show(inputStateHandler);

UpdateManager.Options uOptions = new UpdateManager.Options();

Expand Down Expand Up @@ -111,7 +114,7 @@ private void startup(String[] args) {
try {
ui.executeManager(() -> {
try {
new UpdateManager(uOptions, ui);
new UpdateManager(uOptions, ui, inputStateHandler);
} catch (Exception e) {
// TODO: better error message?
ui.handleExceptionAndExit(e);
Expand Down
109 changes: 93 additions & 16 deletions src/main/java/link/infra/packwiz/installer/UpdateManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import link.infra.packwiz.installer.request.HandlerManager;
import link.infra.packwiz.installer.ui.IExceptionDetails;
import link.infra.packwiz.installer.ui.IUserInterface;
import link.infra.packwiz.installer.ui.InputStateHandler;
import link.infra.packwiz.installer.ui.InstallProgress;
import okio.Okio;
import okio.Source;
Expand All @@ -33,6 +34,7 @@ public class UpdateManager {
public final IUserInterface ui;
private boolean cancelled;
private boolean cancelledStartGame = false;
private InputStateHandler stateHandler;

public static class Options {
SpaceSafeURI downloadURI = null;
Expand Down Expand Up @@ -92,9 +94,10 @@ public static Side from(String name) {
}
}

UpdateManager(Options opts, IUserInterface ui) {
UpdateManager(Options opts, IUserInterface ui, InputStateHandler inputStateHandler) {
this.opts = opts;
this.ui = ui;
this.stateHandler = inputStateHandler;
this.start();
}

Expand All @@ -114,6 +117,11 @@ private void start() {
return;
}

if (stateHandler.getCancelButton()) {
showCancellationDialog();
handleCancellation();
}

ui.submitProgress(new InstallProgress("Loading pack file..."));
GeneralHashingSource packFileSource;
try {
Expand All @@ -133,6 +141,11 @@ private void start() {
return;
}

if (stateHandler.getCancelButton()) {
showCancellationDialog();
handleCancellation();
}

ui.submitProgress(new InstallProgress("Checking local files..."));

// Invalidation checking must be done here, as it must happen before pack/index hashes are checked
Expand Down Expand Up @@ -162,11 +175,18 @@ private void start() {
if (manifest.packFileHash != null && packFileSource.hashIsEqual(manifest.packFileHash) && invalidatedUris.isEmpty()) {
System.out.println("Modpack is already up to date!");
// todo: --force?
return;
if (!stateHandler.getOptionsButton()) {
return;
}
}

System.out.println("Modpack name: " + pf.name);

if (stateHandler.getCancelButton()) {
showCancellationDialog();
handleCancellation();
}

try {
// This is badly written, I'll probably heavily refactor it at some point
processIndex(HandlerManager.getNewLoc(opts.downloadURI, pf.index.file),
Expand All @@ -175,15 +195,7 @@ private void start() {
ui.handleExceptionAndExit(e1);
}

if (cancelled) {
System.out.println("Update cancelled by user!");
System.exit(1);
return;
} else if (cancelledStartGame) {
System.out.println("Update cancelled by user! Continuing to start game...");
System.exit(0);
return;
}
handleCancellation();

// TODO: update MMC params, java args etc

Expand All @@ -205,7 +217,9 @@ private void checkOptions() {
private void processIndex(SpaceSafeURI indexUri, Hash indexHash, String hashFormat, ManifestFile manifest, List<SpaceSafeURI> invalidatedUris) {
if (manifest.indexFileHash != null && manifest.indexFileHash.equals(indexHash) && invalidatedUris.isEmpty()) {
System.out.println("Modpack files are already up to date!");
return;
if (!stateHandler.getOptionsButton()) {
return;
}
}
manifest.indexFileHash = indexHash;

Expand Down Expand Up @@ -233,6 +247,11 @@ private void processIndex(SpaceSafeURI indexUri, Hash indexHash, String hashForm
return;
}

if (stateHandler.getCancelButton()) {
showCancellationDialog();
return;
}

if (manifest.cachedFiles == null) {
manifest.cachedFiles = new HashMap<>();
}
Expand Down Expand Up @@ -269,13 +288,21 @@ private void processIndex(SpaceSafeURI indexUri, Hash indexHash, String hashForm
}
}
}

if (stateHandler.getCancelButton()) {
showCancellationDialog();
return;
}
ui.submitProgress(new InstallProgress("Comparing new files..."));

// TODO: progress bar, parallelify
// TODO: progress bar?
List<DownloadTask> tasks = DownloadTask.createTasksFromIndex(indexFile, indexFile.hashFormat, opts.side);
// If the side changes, invalidate EVERYTHING just in case
// Might not be needed, but done just to be safe
boolean invalidateAll = !opts.side.equals(manifest.cachedSide);
if (invalidateAll) {
System.out.println("Side changed, invalidating all mods");
}
tasks.forEach(f -> {
// TODO: should linkedfile be checked as well? should this be done in the download section?
if (invalidateAll) {
Expand All @@ -291,7 +318,14 @@ private void processIndex(SpaceSafeURI indexUri, Hash indexHash, String hashForm
// If it is null, the DownloadTask will make a new empty cachedFile
f.updateFromCache(file);
});
tasks.forEach(f -> f.downloadMetadata(indexFile, indexUri));

if (stateHandler.getCancelButton()) {
showCancellationDialog();
return;
}

// Let's hope downloadMetadata is a pure function!!!
tasks.parallelStream().forEach(f -> f.downloadMetadata(indexFile, indexUri));

List<IExceptionDetails> failedTasks = tasks.stream().filter(t -> t.getException() != null).collect(Collectors.toList());
if (failedTasks.size() > 0) {
Expand All @@ -315,10 +349,15 @@ private void processIndex(SpaceSafeURI indexUri, Hash indexHash, String hashForm
}
}

if (stateHandler.getCancelButton()) {
showCancellationDialog();
return;
}

List<DownloadTask> nonFailedFirstTasks = tasks.stream().filter(t -> t.getException() == null).collect(Collectors.toList());
List<DownloadTask> optionTasks = nonFailedFirstTasks.stream().filter(DownloadTask::correctSide).filter(DownloadTask::isOptional).collect(Collectors.toList());
// If options changed, present all options again
if (optionTasks.stream().anyMatch(DownloadTask::isNewOptional)) {
if (stateHandler.getOptionsButton() || optionTasks.stream().anyMatch(DownloadTask::isNewOptional)) {
// new ArrayList is requires so it's an IOptionDetails rather than a DownloadTask list
Future<Boolean> cancelledResult = ui.showOptions(new ArrayList<>(optionTasks));
try {
Expand All @@ -332,6 +371,7 @@ private void processIndex(SpaceSafeURI indexUri, Hash indexHash, String hashForm
ui.handleExceptionAndExit(e);
}
}
ui.disableOptionsButton();

// TODO: different thread pool type?
ExecutorService threadPool = Executors.newFixedThreadPool(10);
Expand All @@ -355,7 +395,7 @@ private void processIndex(SpaceSafeURI indexUri, Hash indexHash, String hashForm
if (task.getException() != null) {
ManifestFile.File file = task.cachedFile.getRevert();
if (file != null) {
manifest.cachedFiles.put(task.metadata.file, file);
manifest.cachedFiles.putIfAbsent(task.metadata.file, file);
}
} else {
// idiot, if it wasn't there in the first place it won't magically appear there
Expand All @@ -376,6 +416,13 @@ private void processIndex(SpaceSafeURI indexUri, Hash indexHash, String hashForm
progress = "Failed to download, unknown reason";
}
ui.submitProgress(new InstallProgress(progress, i + 1, tasks.size()));

if (stateHandler.getCancelButton()) {
// Stop all tasks, don't launch the game (it's in an invalid state!)
threadPool.shutdown();
cancelled = true;
return;
}
}

List<IExceptionDetails> failedTasks2ElectricBoogaloo = nonFailedFirstTasks.stream().filter(t -> t.getException() != null).collect(Collectors.toList());
Expand All @@ -399,4 +446,34 @@ private void processIndex(SpaceSafeURI indexUri, Hash indexHash, String hashForm
}
}
}

private void showCancellationDialog() {
IExceptionDetails.ExceptionListResult exceptionListResult;
try {
exceptionListResult = ui.showCancellationDialog().get();
} catch (InterruptedException | ExecutionException e) {
// Interrupted means cancelled???
ui.handleExceptionAndExit(e);
return;
}
switch (exceptionListResult) {
case CONTINUE:
throw new RuntimeException("Continuation not allowed here!");
case CANCEL:
cancelled = true;
return;
case IGNORE:
cancelledStartGame = true;
}
}

private void handleCancellation() {
if (cancelled) {
System.out.println("Update cancelled by user!");
System.exit(1);
} else if (cancelledStartGame) {
System.out.println("Update cancelled by user! Continuing to start game...");
System.exit(0);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ public static class File {

public transient ModFile linkedFile;
public transient SpaceSafeURI linkedFileURI;
public transient boolean optionValue = true;

public void downloadMeta(IndexFile parentIndexFile, SpaceSafeURI indexUri) throws Exception {
if (!metafile) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public void handleException(Exception e) {
}

@Override
public void show() {}
public void show(InputStateHandler h) {}

@Override
public void submitProgress(InstallProgress progress) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package link.infra.packwiz.installer.ui;

import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;

public interface IUserInterface {

void show();
void show(InputStateHandler handler);

void handleException(Exception e);

Expand All @@ -24,5 +25,14 @@ default void setTitle(String title) {}
Future<Boolean> showOptions(List<IOptionDetails> option);

Future<IExceptionDetails.ExceptionListResult> showExceptions(List<IExceptionDetails> opts, int numTotal, boolean allowsIgnore);

default void disableOptionsButton() {}

// Should not return CONTINUE
default Future<IExceptionDetails.ExceptionListResult> showCancellationDialog() {
CompletableFuture<IExceptionDetails.ExceptionListResult> future = new CompletableFuture<>();
future.complete(IExceptionDetails.ExceptionListResult.CANCEL);
return future;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package link.infra.packwiz.installer.ui;

public class InputStateHandler {
private boolean optionsButtonPressed = false;
private boolean cancelButtonPressed = false;

synchronized void pressCancelButton() {
this.cancelButtonPressed = true;
}

synchronized void pressOptionsButton() {
this.optionsButtonPressed = true;
}

public synchronized boolean getCancelButton() {
return cancelButtonPressed;
}

public synchronized boolean getOptionsButton() {
return optionsButtonPressed;
}
}
Loading

0 comments on commit 7946377

Please sign in to comment.