mirror of
https://github.com/SKCraft/Launcher.git
synced 2024-11-24 12:16:28 +01:00
Split up LauncherFrame.
This commit is contained in:
parent
415de32f6a
commit
8cf14a5ce1
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* SKCraft Launcher
|
||||||
|
* Copyright (C) 2010-2014 Albert Pham <http://www.sk89q.com> and contributors
|
||||||
|
* Please see LICENSE.txt for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.skcraft.launcher;
|
||||||
|
|
||||||
|
import com.skcraft.concurrency.ObservableFuture;
|
||||||
|
import com.skcraft.launcher.dialog.ProgressDialog;
|
||||||
|
import com.skcraft.launcher.swing.SwingHelper;
|
||||||
|
import com.skcraft.launcher.update.HardResetter;
|
||||||
|
import com.skcraft.launcher.update.Remover;
|
||||||
|
import com.skcraft.launcher.util.SharedLocale;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
|
||||||
|
import static com.skcraft.launcher.util.SharedLocale.tr;
|
||||||
|
|
||||||
|
public class InstanceTasks {
|
||||||
|
|
||||||
|
private final Launcher launcher;
|
||||||
|
|
||||||
|
public InstanceTasks(Launcher launcher) {
|
||||||
|
this.launcher = launcher;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObservableFuture<Instance> delete(Window window, Instance instance) {
|
||||||
|
// Execute the deleter
|
||||||
|
Remover resetter = new Remover(instance);
|
||||||
|
ObservableFuture<Instance> future = new ObservableFuture<Instance>(
|
||||||
|
launcher.getExecutor().submit(resetter), resetter);
|
||||||
|
|
||||||
|
// Show progress
|
||||||
|
ProgressDialog.showProgress(
|
||||||
|
window, future, SharedLocale.tr("instance.deletingTitle"), tr("instance.deletingStatus", instance.getTitle()));
|
||||||
|
SwingHelper.addErrorDialogCallback(window, future);
|
||||||
|
|
||||||
|
return future;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObservableFuture<Instance> hardUpdate(Window window, Instance instance) {
|
||||||
|
// Execute the resetter
|
||||||
|
HardResetter resetter = new HardResetter(instance);
|
||||||
|
ObservableFuture<Instance> future = new ObservableFuture<Instance>(
|
||||||
|
launcher.getExecutor().submit(resetter), resetter);
|
||||||
|
|
||||||
|
// Show progress
|
||||||
|
ProgressDialog.showProgress(window, future, SharedLocale.tr("instance.resettingTitle"),
|
||||||
|
tr("instance.resettingStatus", instance.getTitle()));
|
||||||
|
SwingHelper.addErrorDialogCallback(window, future);
|
||||||
|
|
||||||
|
return future;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObservableFuture<InstanceList> reloadInstances(Window window) {
|
||||||
|
InstanceList.Enumerator loader = launcher.getInstances().createEnumerator();
|
||||||
|
ObservableFuture<InstanceList> future = new ObservableFuture<InstanceList>(launcher.getExecutor().submit(loader), loader);
|
||||||
|
|
||||||
|
ProgressDialog.showProgress(window, future, SharedLocale.tr("launcher.checkingTitle"), SharedLocale.tr("launcher.checkingStatus"));
|
||||||
|
SwingHelper.addErrorDialogCallback(window, future);
|
||||||
|
|
||||||
|
return future;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -15,9 +15,11 @@ import com.skcraft.launcher.auth.AccountList;
|
|||||||
import com.skcraft.launcher.auth.LoginService;
|
import com.skcraft.launcher.auth.LoginService;
|
||||||
import com.skcraft.launcher.auth.YggdrasilLoginService;
|
import com.skcraft.launcher.auth.YggdrasilLoginService;
|
||||||
import com.skcraft.launcher.dialog.LauncherFrame;
|
import com.skcraft.launcher.dialog.LauncherFrame;
|
||||||
|
import com.skcraft.launcher.launch.LaunchSupervisor;
|
||||||
import com.skcraft.launcher.model.minecraft.VersionManifest;
|
import com.skcraft.launcher.model.minecraft.VersionManifest;
|
||||||
import com.skcraft.launcher.persistence.Persistence;
|
import com.skcraft.launcher.persistence.Persistence;
|
||||||
import com.skcraft.launcher.swing.SwingHelper;
|
import com.skcraft.launcher.swing.SwingHelper;
|
||||||
|
import com.skcraft.launcher.update.UpdateManager;
|
||||||
import com.skcraft.launcher.util.HttpRequest;
|
import com.skcraft.launcher.util.HttpRequest;
|
||||||
import com.skcraft.launcher.util.SharedLocale;
|
import com.skcraft.launcher.util.SharedLocale;
|
||||||
import com.skcraft.launcher.util.SimpleLogFormatter;
|
import com.skcraft.launcher.util.SimpleLogFormatter;
|
||||||
@ -54,6 +56,9 @@ public final class Launcher {
|
|||||||
@Getter private final Configuration config;
|
@Getter private final Configuration config;
|
||||||
@Getter private final AccountList accounts;
|
@Getter private final AccountList accounts;
|
||||||
@Getter private final AssetsRoot assets;
|
@Getter private final AssetsRoot assets;
|
||||||
|
@Getter private final LaunchSupervisor launchSupervisor = new LaunchSupervisor(this);
|
||||||
|
@Getter private final UpdateManager updateManager = new UpdateManager(this);
|
||||||
|
@Getter private final InstanceTasks instanceTasks = new InstanceTasks(this);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new launcher instance with the given base directory.
|
* Create a new launcher instance with the given base directory.
|
||||||
@ -82,6 +87,8 @@ public final class Launcher {
|
|||||||
cleanupExtractDir();
|
cleanupExtractDir();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
updateManager.checkForUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -6,29 +6,17 @@
|
|||||||
|
|
||||||
package com.skcraft.launcher.dialog;
|
package com.skcraft.launcher.dialog;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.FutureCallback;
|
|
||||||
import com.google.common.util.concurrent.Futures;
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
|
||||||
import com.skcraft.concurrency.ObservableFuture;
|
import com.skcraft.concurrency.ObservableFuture;
|
||||||
import com.skcraft.launcher.Instance;
|
import com.skcraft.launcher.Instance;
|
||||||
import com.skcraft.launcher.InstanceList;
|
import com.skcraft.launcher.InstanceList;
|
||||||
import com.skcraft.launcher.Launcher;
|
import com.skcraft.launcher.Launcher;
|
||||||
import com.skcraft.launcher.auth.Session;
|
import com.skcraft.launcher.launch.LaunchListener;
|
||||||
import com.skcraft.launcher.launch.Runner;
|
|
||||||
import com.skcraft.launcher.launch.LaunchProcessHandler;
|
|
||||||
import com.skcraft.launcher.persistence.Persistence;
|
|
||||||
import com.skcraft.launcher.selfupdate.UpdateChecker;
|
|
||||||
import com.skcraft.launcher.selfupdate.SelfUpdater;
|
|
||||||
import com.skcraft.launcher.swing.*;
|
import com.skcraft.launcher.swing.*;
|
||||||
import com.skcraft.launcher.update.HardResetter;
|
|
||||||
import com.skcraft.launcher.update.Remover;
|
|
||||||
import com.skcraft.launcher.update.Updater;
|
|
||||||
import com.skcraft.launcher.util.SharedLocale;
|
import com.skcraft.launcher.util.SharedLocale;
|
||||||
import com.skcraft.launcher.util.SwingExecutor;
|
import com.skcraft.launcher.util.SwingExecutor;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import lombok.extern.java.Log;
|
import lombok.extern.java.Log;
|
||||||
import net.miginfocom.swing.MigLayout;
|
import net.miginfocom.swing.MigLayout;
|
||||||
import org.apache.commons.io.FileUtils;
|
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.event.TableModelEvent;
|
import javax.swing.event.TableModelEvent;
|
||||||
@ -37,13 +25,11 @@ import java.awt.*;
|
|||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
|
import java.beans.PropertyChangeEvent;
|
||||||
|
import java.beans.PropertyChangeListener;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.Date;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
|
|
||||||
import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
|
|
||||||
import static com.skcraft.launcher.util.SharedLocale.tr;
|
import static com.skcraft.launcher.util.SharedLocale.tr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -87,7 +73,6 @@ public class LauncherFrame extends JFrame {
|
|||||||
SwingHelper.setIconImage(this, Launcher.class, "icon.png");
|
SwingHelper.setIconImage(this, Launcher.class, "icon.png");
|
||||||
|
|
||||||
loadInstances();
|
loadInstances();
|
||||||
checkLauncherUpdate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initComponents() {
|
private void initComponents() {
|
||||||
@ -95,7 +80,17 @@ public class LauncherFrame extends JFrame {
|
|||||||
|
|
||||||
webView = WebpagePanel.forURL(launcher.getNewsURL(), false);
|
webView = WebpagePanel.forURL(launcher.getNewsURL(), false);
|
||||||
splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, instanceScroll, webView);
|
splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, instanceScroll, webView);
|
||||||
selfUpdateButton.setVisible(false);
|
selfUpdateButton.setVisible(launcher.getUpdateManager().getPendingUpdate());
|
||||||
|
|
||||||
|
launcher.getUpdateManager().addPropertyChangeListener(new PropertyChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void propertyChange(PropertyChangeEvent evt) {
|
||||||
|
if (evt.getPropertyName().equals("pendingUpdate")) {
|
||||||
|
selfUpdateButton.setVisible((Boolean) evt.getNewValue());
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
updateCheck.setSelected(true);
|
updateCheck.setSelected(true);
|
||||||
instancesTable.setModel(instancesModel);
|
instancesTable.setModel(instancesModel);
|
||||||
@ -125,14 +120,14 @@ public class LauncherFrame extends JFrame {
|
|||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
loadInstances();
|
loadInstances();
|
||||||
checkLauncherUpdate();
|
launcher.getUpdateManager().checkForUpdate();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
selfUpdateButton.addActionListener(new ActionListener() {
|
selfUpdateButton.addActionListener(new ActionListener() {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
selfUpdate();
|
launcher.getUpdateManager().performUpdate(LauncherFrame.this);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -164,64 +159,6 @@ public class LauncherFrame extends JFrame {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkLauncherUpdate() {
|
|
||||||
if (SelfUpdater.updatedAlready) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ListenableFuture<URL> future = launcher.getExecutor().submit(new UpdateChecker(launcher));
|
|
||||||
|
|
||||||
Futures.addCallback(future, new FutureCallback<URL>() {
|
|
||||||
@Override
|
|
||||||
public void onSuccess(URL result) {
|
|
||||||
if (result != null) {
|
|
||||||
requestUpdate(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailure(Throwable t) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}, SwingExecutor.INSTANCE);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void selfUpdate() {
|
|
||||||
URL url = updateUrl;
|
|
||||||
if (url != null) {
|
|
||||||
SelfUpdater downloader = new SelfUpdater(launcher, url);
|
|
||||||
ObservableFuture<File> future = new ObservableFuture<File>(
|
|
||||||
launcher.getExecutor().submit(downloader), downloader);
|
|
||||||
|
|
||||||
Futures.addCallback(future, new FutureCallback<File>() {
|
|
||||||
@Override
|
|
||||||
public void onSuccess(File result) {
|
|
||||||
selfUpdateButton.setVisible(false);
|
|
||||||
SwingHelper.showMessageDialog(
|
|
||||||
LauncherFrame.this,
|
|
||||||
SharedLocale.tr("launcher.selfUpdateComplete"),
|
|
||||||
SharedLocale.tr("launcher.selfUpdateCompleteTitle"),
|
|
||||||
null,
|
|
||||||
JOptionPane.INFORMATION_MESSAGE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailure(Throwable t) {
|
|
||||||
}
|
|
||||||
}, SwingExecutor.INSTANCE);
|
|
||||||
|
|
||||||
ProgressDialog.showProgress(this, future, SharedLocale.tr("launcher.selfUpdatingTitle"), SharedLocale.tr("launcher.selfUpdatingStatus"));
|
|
||||||
SwingHelper.addErrorDialogCallback(this, future);
|
|
||||||
} else {
|
|
||||||
selfUpdateButton.setVisible(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void requestUpdate(URL url) {
|
|
||||||
this.updateUrl = url;
|
|
||||||
selfUpdateButton.setVisible(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Popup the menu for the instances.
|
* Popup the menu for the instances.
|
||||||
*
|
*
|
||||||
@ -334,15 +271,7 @@ public class LauncherFrame extends JFrame {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute the deleter
|
ObservableFuture<Instance> future = launcher.getInstanceTasks().delete(this, instance);
|
||||||
Remover resetter = new Remover(instance);
|
|
||||||
ObservableFuture<Instance> future = new ObservableFuture<Instance>(
|
|
||||||
launcher.getExecutor().submit(resetter), resetter);
|
|
||||||
|
|
||||||
// Show progress
|
|
||||||
ProgressDialog.showProgress(
|
|
||||||
this, future, SharedLocale.tr("instance.deletingTitle"), tr("instance.deletingStatus", instance.getTitle()));
|
|
||||||
SwingHelper.addErrorDialogCallback(this, future);
|
|
||||||
|
|
||||||
// Update the list of instances after updating
|
// Update the list of instances after updating
|
||||||
future.addListener(new Runnable() {
|
future.addListener(new Runnable() {
|
||||||
@ -358,15 +287,7 @@ public class LauncherFrame extends JFrame {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute the resetter
|
ObservableFuture<Instance> future = launcher.getInstanceTasks().hardUpdate(this, instance);
|
||||||
HardResetter resetter = new HardResetter(instance);
|
|
||||||
ObservableFuture<Instance> future = new ObservableFuture<Instance>(
|
|
||||||
launcher.getExecutor().submit(resetter), resetter);
|
|
||||||
|
|
||||||
// Show progress
|
|
||||||
ProgressDialog.showProgress( this, future, SharedLocale.tr("instance.resettingTitle"),
|
|
||||||
tr("instance.resettingStatus", instance.getTitle()));
|
|
||||||
SwingHelper.addErrorDialogCallback(this, future);
|
|
||||||
|
|
||||||
// Update the list of instances after updating
|
// Update the list of instances after updating
|
||||||
future.addListener(new Runnable() {
|
future.addListener(new Runnable() {
|
||||||
@ -379,9 +300,7 @@ public class LauncherFrame extends JFrame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void loadInstances() {
|
private void loadInstances() {
|
||||||
InstanceList.Enumerator loader = launcher.getInstances().createEnumerator();
|
ObservableFuture<InstanceList> future = launcher.getInstanceTasks().reloadInstances(this);
|
||||||
ObservableFuture<InstanceList> future = new ObservableFuture<InstanceList>(
|
|
||||||
launcher.getExecutor().submit(loader), loader);
|
|
||||||
|
|
||||||
future.addListener(new Runnable() {
|
future.addListener(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
@ -404,107 +323,25 @@ public class LauncherFrame extends JFrame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void launch() {
|
private void launch() {
|
||||||
try {
|
boolean permitUpdate = updateCheck.isSelected();
|
||||||
final Instance instance = launcher.getInstances().get(instancesTable.getSelectedRow());
|
Instance instance = launcher.getInstances().get(instancesTable.getSelectedRow());
|
||||||
boolean update = updateCheck.isSelected() && instance.isUpdatePending();
|
|
||||||
|
|
||||||
// Store last access date
|
launcher.getLaunchSupervisor().launch(this, instance, permitUpdate, new LaunchListener() {
|
||||||
Date now = new Date();
|
|
||||||
instance.setLastAccessed(now);
|
|
||||||
Persistence.commitAndForget(instance);
|
|
||||||
|
|
||||||
// Perform login
|
|
||||||
final Session session = LoginDialog.showLoginRequest(this, launcher);
|
|
||||||
if (session == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we have to update, we have to update
|
|
||||||
if (!instance.isInstalled()) {
|
|
||||||
update = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (update) {
|
|
||||||
// Execute the updater
|
|
||||||
Updater updater = new Updater(launcher, instance);
|
|
||||||
updater.setOnline(session.isOnline());
|
|
||||||
ObservableFuture<Instance> future = new ObservableFuture<Instance>(
|
|
||||||
launcher.getExecutor().submit(updater), updater);
|
|
||||||
|
|
||||||
// Show progress
|
|
||||||
ProgressDialog.showProgress(
|
|
||||||
this, future, SharedLocale.tr("launcher.updatingTitle"), tr("launcher.updatingStatus", instance.getTitle()));
|
|
||||||
SwingHelper.addErrorDialogCallback(this, future);
|
|
||||||
|
|
||||||
// Update the list of instances after updating
|
|
||||||
future.addListener(new Runnable() {
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void instancesUpdated() {
|
||||||
instancesModel.update();
|
instancesModel.update();
|
||||||
}
|
}
|
||||||
}, SwingExecutor.INSTANCE);
|
|
||||||
|
|
||||||
// On success, launch also
|
|
||||||
Futures.addCallback(future, new FutureCallback<Instance>() {
|
|
||||||
@Override
|
|
||||||
public void onSuccess(Instance result) {
|
|
||||||
launch(instance, session);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFailure(Throwable t) {
|
public void gameStarted() {
|
||||||
}
|
|
||||||
}, SwingExecutor.INSTANCE);
|
|
||||||
} else {
|
|
||||||
launch(instance, session);
|
|
||||||
}
|
|
||||||
} catch (ArrayIndexOutOfBoundsException e) {
|
|
||||||
SwingHelper.showErrorDialog(this, SharedLocale.tr("launcher.noInstanceError"), SharedLocale.tr("launcher.noInstanceTitle"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void launch(Instance instance, Session session) {
|
|
||||||
final File extractDir = launcher.createExtractDir();
|
|
||||||
|
|
||||||
// Get the process
|
|
||||||
Runner task = new Runner(launcher, instance, session, extractDir);
|
|
||||||
ObservableFuture<Process> processFuture = new ObservableFuture<Process>(
|
|
||||||
launcher.getExecutor().submit(task), task);
|
|
||||||
|
|
||||||
// Show process for the process retrieval
|
|
||||||
ProgressDialog.showProgress(
|
|
||||||
this, processFuture, SharedLocale.tr("launcher.launchingTItle"), tr("launcher.launchingStatus", instance.getTitle()));
|
|
||||||
|
|
||||||
// If the process is started, get rid of this window
|
|
||||||
Futures.addCallback(processFuture, new FutureCallback<Process>() {
|
|
||||||
@Override
|
|
||||||
public void onSuccess(Process result) {
|
|
||||||
dispose();
|
dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFailure(Throwable t) {
|
public void gameClosed() {
|
||||||
|
new LauncherFrame(launcher).setVisible(true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Watch the created process
|
|
||||||
ListenableFuture<?> future = Futures.transform(
|
|
||||||
processFuture, new LaunchProcessHandler(launcher), launcher.getExecutor());
|
|
||||||
SwingHelper.addErrorDialogCallback(null, future);
|
|
||||||
|
|
||||||
// Clean up at the very end
|
|
||||||
future.addListener(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
log.info("Process ended; cleaning up " + extractDir.getAbsolutePath());
|
|
||||||
FileUtils.deleteDirectory(extractDir);
|
|
||||||
} catch (IOException e) {
|
|
||||||
log.log(Level.WARNING, "Failed to clean up " + extractDir.getAbsolutePath(), e);
|
|
||||||
}
|
|
||||||
instancesModel.update();
|
|
||||||
}
|
|
||||||
}, sameThreadExecutor());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
* SKCraft Launcher
|
||||||
|
* Copyright (C) 2010-2014 Albert Pham <http://www.sk89q.com> and contributors
|
||||||
|
* Please see LICENSE.txt for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.skcraft.launcher.launch;
|
||||||
|
|
||||||
|
public interface LaunchListener {
|
||||||
|
|
||||||
|
public void instancesUpdated();
|
||||||
|
|
||||||
|
public void gameStarted();
|
||||||
|
|
||||||
|
public void gameClosed();
|
||||||
|
|
||||||
|
}
|
@ -64,8 +64,6 @@ public class LaunchProcessHandler implements Function<Process, ProcessConsoleFra
|
|||||||
SwingUtilities.invokeLater(new Runnable() {
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
new LauncherFrame(launcher).setVisible(true);
|
|
||||||
|
|
||||||
if (consoleFrame != null) {
|
if (consoleFrame != null) {
|
||||||
consoleFrame.setProcess(null);
|
consoleFrame.setProcess(null);
|
||||||
consoleFrame.requestFocus();
|
consoleFrame.requestFocus();
|
||||||
|
@ -0,0 +1,162 @@
|
|||||||
|
/*
|
||||||
|
* SKCraft Launcher
|
||||||
|
* Copyright (C) 2010-2014 Albert Pham <http://www.sk89q.com> and contributors
|
||||||
|
* Please see LICENSE.txt for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.skcraft.launcher.launch;
|
||||||
|
|
||||||
|
import com.google.common.util.concurrent.FutureCallback;
|
||||||
|
import com.google.common.util.concurrent.Futures;
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
import com.skcraft.concurrency.ObservableFuture;
|
||||||
|
import com.skcraft.launcher.Instance;
|
||||||
|
import com.skcraft.launcher.Launcher;
|
||||||
|
import com.skcraft.launcher.auth.Session;
|
||||||
|
import com.skcraft.launcher.dialog.LoginDialog;
|
||||||
|
import com.skcraft.launcher.dialog.ProgressDialog;
|
||||||
|
import com.skcraft.launcher.persistence.Persistence;
|
||||||
|
import com.skcraft.launcher.swing.SwingHelper;
|
||||||
|
import com.skcraft.launcher.update.Updater;
|
||||||
|
import com.skcraft.launcher.util.SharedLocale;
|
||||||
|
import com.skcraft.launcher.util.SwingExecutor;
|
||||||
|
import lombok.extern.java.Log;
|
||||||
|
import org.apache.commons.io.FileUtils;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
|
||||||
|
import static com.skcraft.launcher.util.SharedLocale.tr;
|
||||||
|
|
||||||
|
@Log
|
||||||
|
public class LaunchSupervisor {
|
||||||
|
|
||||||
|
private final Launcher launcher;
|
||||||
|
|
||||||
|
public LaunchSupervisor(Launcher launcher) {
|
||||||
|
this.launcher = launcher;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void launch(final Window window, final Instance instance, boolean permitUpdate, final LaunchListener listener) {
|
||||||
|
try {
|
||||||
|
boolean update = permitUpdate && instance.isUpdatePending();
|
||||||
|
|
||||||
|
// Store last access date
|
||||||
|
Date now = new Date();
|
||||||
|
instance.setLastAccessed(now);
|
||||||
|
Persistence.commitAndForget(instance);
|
||||||
|
|
||||||
|
// Perform login
|
||||||
|
final Session session = LoginDialog.showLoginRequest(window, launcher);
|
||||||
|
if (session == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have to update, we have to update
|
||||||
|
if (!instance.isInstalled()) {
|
||||||
|
update = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (update) {
|
||||||
|
// Execute the updater
|
||||||
|
Updater updater = new Updater(launcher, instance);
|
||||||
|
updater.setOnline(session.isOnline());
|
||||||
|
ObservableFuture<Instance> future = new ObservableFuture<Instance>(
|
||||||
|
launcher.getExecutor().submit(updater), updater);
|
||||||
|
|
||||||
|
// Show progress
|
||||||
|
ProgressDialog.showProgress(window, future, SharedLocale.tr("launcher.updatingTitle"), tr("launcher.updatingStatus", instance.getTitle()));
|
||||||
|
SwingHelper.addErrorDialogCallback(window, future);
|
||||||
|
|
||||||
|
// Update the list of instances after updating
|
||||||
|
future.addListener(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
listener.instancesUpdated();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, SwingExecutor.INSTANCE);
|
||||||
|
|
||||||
|
// On success, launch also
|
||||||
|
Futures.addCallback(future, new FutureCallback<Instance>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(Instance result) {
|
||||||
|
launch(window, instance, session, listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Throwable t) {
|
||||||
|
}
|
||||||
|
}, SwingExecutor.INSTANCE);
|
||||||
|
} else {
|
||||||
|
launch(window, instance, session, listener);
|
||||||
|
}
|
||||||
|
} catch (ArrayIndexOutOfBoundsException e) {
|
||||||
|
SwingHelper.showErrorDialog(window, SharedLocale.tr("launcher.noInstanceError"), SharedLocale.tr("launcher.noInstanceTitle"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void launch(Window window, Instance instance, Session session, final LaunchListener listener) {
|
||||||
|
final File extractDir = launcher.createExtractDir();
|
||||||
|
|
||||||
|
// Get the process
|
||||||
|
Runner task = new Runner(launcher, instance, session, extractDir);
|
||||||
|
ObservableFuture<Process> processFuture = new ObservableFuture<Process>(
|
||||||
|
launcher.getExecutor().submit(task), task);
|
||||||
|
|
||||||
|
// Show process for the process retrieval
|
||||||
|
ProgressDialog.showProgress(
|
||||||
|
window, processFuture, SharedLocale.tr("launcher.launchingTItle"), tr("launcher.launchingStatus", instance.getTitle()));
|
||||||
|
|
||||||
|
// If the process is started, get rid of this window
|
||||||
|
Futures.addCallback(processFuture, new FutureCallback<Process>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(Process result) {
|
||||||
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
listener.gameStarted();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Throwable t) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Watch the created process
|
||||||
|
ListenableFuture<?> future = Futures.transform(
|
||||||
|
processFuture, new LaunchProcessHandler(launcher), launcher.getExecutor());
|
||||||
|
SwingHelper.addErrorDialogCallback(null, future);
|
||||||
|
|
||||||
|
// Clean up at the very end
|
||||||
|
future.addListener(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
log.info("Process ended; cleaning up " + extractDir.getAbsolutePath());
|
||||||
|
FileUtils.deleteDirectory(extractDir);
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.log(Level.WARNING, "Failed to clean up " + extractDir.getAbsolutePath(), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
listener.gameClosed();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, sameThreadExecutor());
|
||||||
|
}
|
||||||
|
}
|
@ -22,8 +22,6 @@ import java.util.concurrent.Executors;
|
|||||||
|
|
||||||
public class SelfUpdater implements Callable<File>, ProgressObservable {
|
public class SelfUpdater implements Callable<File>, ProgressObservable {
|
||||||
|
|
||||||
public static boolean updatedAlready = false;
|
|
||||||
|
|
||||||
private final Launcher launcher;
|
private final Launcher launcher;
|
||||||
private final URL url;
|
private final URL url;
|
||||||
private final Installer installer;
|
private final Installer installer;
|
||||||
@ -52,8 +50,6 @@ public class SelfUpdater implements Callable<File>, ProgressObservable {
|
|||||||
progress = installer;
|
progress = installer;
|
||||||
installer.execute();
|
installer.execute();
|
||||||
|
|
||||||
updatedAlready = true;
|
|
||||||
|
|
||||||
return file;
|
return file;
|
||||||
} finally {
|
} finally {
|
||||||
executor.shutdownNow();
|
executor.shutdownNow();
|
||||||
|
@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
* SKCraft Launcher
|
||||||
|
* Copyright (C) 2010-2014 Albert Pham <http://www.sk89q.com> and contributors
|
||||||
|
* Please see LICENSE.txt for license information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.skcraft.launcher.update;
|
||||||
|
|
||||||
|
import com.google.common.util.concurrent.FutureCallback;
|
||||||
|
import com.google.common.util.concurrent.Futures;
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
import com.skcraft.concurrency.ObservableFuture;
|
||||||
|
import com.skcraft.launcher.Launcher;
|
||||||
|
import com.skcraft.launcher.dialog.ProgressDialog;
|
||||||
|
import com.skcraft.launcher.selfupdate.SelfUpdater;
|
||||||
|
import com.skcraft.launcher.selfupdate.UpdateChecker;
|
||||||
|
import com.skcraft.launcher.swing.SwingHelper;
|
||||||
|
import com.skcraft.launcher.util.SharedLocale;
|
||||||
|
import com.skcraft.launcher.util.SwingExecutor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.event.SwingPropertyChangeSupport;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.beans.PropertyChangeListener;
|
||||||
|
import java.io.File;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
public class UpdateManager {
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private final SwingPropertyChangeSupport propertySupport = new SwingPropertyChangeSupport(this);
|
||||||
|
private final Launcher launcher;
|
||||||
|
private URL pendingUpdateUrl;
|
||||||
|
|
||||||
|
public UpdateManager(Launcher launcher) {
|
||||||
|
this.launcher = launcher;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addPropertyChangeListener(PropertyChangeListener listener) {
|
||||||
|
propertySupport.addPropertyChangeListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removePropertyChangeListener(PropertyChangeListener listener) {
|
||||||
|
propertySupport.removePropertyChangeListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getPendingUpdate() {
|
||||||
|
return pendingUpdateUrl != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkForUpdate() {
|
||||||
|
ListenableFuture<URL> future = launcher.getExecutor().submit(new UpdateChecker(launcher));
|
||||||
|
|
||||||
|
Futures.addCallback(future, new FutureCallback<URL>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(URL result) {
|
||||||
|
if (result != null) {
|
||||||
|
requestUpdate(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Throwable t) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}, SwingExecutor.INSTANCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void performUpdate(final Window window) {
|
||||||
|
final URL url = pendingUpdateUrl;
|
||||||
|
|
||||||
|
if (url != null) {
|
||||||
|
SelfUpdater downloader = new SelfUpdater(launcher, url);
|
||||||
|
ObservableFuture<File> future = new ObservableFuture<File>(
|
||||||
|
launcher.getExecutor().submit(downloader), downloader);
|
||||||
|
|
||||||
|
Futures.addCallback(future, new FutureCallback<File>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(File result) {
|
||||||
|
propertySupport.firePropertyChange("pendingUpdate", true, false);
|
||||||
|
UpdateManager.this.pendingUpdateUrl = null;
|
||||||
|
|
||||||
|
SwingHelper.showMessageDialog(
|
||||||
|
window,
|
||||||
|
SharedLocale.tr("launcher.selfUpdateComplete"),
|
||||||
|
SharedLocale.tr("launcher.selfUpdateCompleteTitle"),
|
||||||
|
null,
|
||||||
|
JOptionPane.INFORMATION_MESSAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Throwable t) {
|
||||||
|
}
|
||||||
|
}, SwingExecutor.INSTANCE);
|
||||||
|
|
||||||
|
ProgressDialog.showProgress(window, future, SharedLocale.tr("launcher.selfUpdatingTitle"), SharedLocale.tr("launcher.selfUpdatingStatus"));
|
||||||
|
SwingHelper.addErrorDialogCallback(window, future);
|
||||||
|
} else {
|
||||||
|
propertySupport.firePropertyChange("pendingUpdate", false, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void requestUpdate(URL url) {
|
||||||
|
propertySupport.firePropertyChange("pendingUpdate", getPendingUpdate(), url != null);
|
||||||
|
this.pendingUpdateUrl = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user