rl-client: open FatalErrorDialog early during outages

This commit is contained in:
Max Weber
2022-03-24 13:55:40 -06:00
parent f2f8a05796
commit fb6f9682bd
7 changed files with 115 additions and 14 deletions

View File

@@ -228,8 +228,8 @@ public class RuneLite
try
{
final ClientLoader clientLoader = new ClientLoader(okHttpClient, options.valueOf(updateMode), (String) options.valueOf("jav_config"));
final RuntimeConfigLoader runtimeConfigLoader = new RuntimeConfigLoader(okHttpClient);
final ClientLoader clientLoader = new ClientLoader(okHttpClient, options.valueOf(updateMode), runtimeConfigLoader, (String) options.valueOf("jav_config"));
new Thread(() ->
{
@@ -247,6 +247,7 @@ public class RuneLite
{
SwingUtilities.invokeLater(() ->
new FatalErrorDialog("Developers should enable assertions; Add `-ea` to your JVM arguments`")
.addHelpButtons()
.addBuildingGuide()
.open());
return;
@@ -282,6 +283,7 @@ public class RuneLite
log.error("Failure during startup", e);
SwingUtilities.invokeLater(() ->
new FatalErrorDialog("RuneLite has encountered an unexpected error during startup.")
.addHelpButtons()
.open());
}
finally

View File

@@ -49,6 +49,7 @@ public class RuneLiteProperties
private static final String PLUGINHUB_VERSION = "runelite.pluginhub.version";
private static final String API_BASE = "runelite.api.base";
private static final String RUNELITE_CONFIG = "runelite.config";
private static final String OSRS_TWITTER_LINK = "runelite.osrstwitter.link";
@Getter(AccessLevel.PACKAGE)
private static final Properties properties = new Properties();
@@ -136,4 +137,9 @@ public class RuneLiteProperties
{
return properties.getProperty(RUNELITE_CONFIG);
}
public static String getOSRSTwitterLink()
{
return properties.getProperty(OSRS_TWITTER_LINK);
}
}

View File

@@ -24,13 +24,46 @@
*/
package net.runelite.client;
import com.google.common.base.Strings;
import java.util.Collections;
import java.util.Map;
import javax.swing.SwingUtilities;
import lombok.Data;
import net.runelite.client.ui.FatalErrorDialog;
import net.runelite.client.util.LinkBrowser;
@Data
public class RuntimeConfig
{
private Map<String, ?> props = Collections.emptyMap();
private Map<String, String> sysProps = Collections.emptyMap();
private String outageMessage;
private Map<String, String> outageLinks;
public boolean showOutageMessage()
{
if (Strings.isNullOrEmpty(getOutageMessage()))
{
return false;
}
SwingUtilities.invokeLater(() ->
{
FatalErrorDialog fed = new FatalErrorDialog(getOutageMessage());
if (getOutageLinks() != null)
{
for (Map.Entry<String, String> e : getOutageLinks().entrySet())
{
fed.addButton(e.getKey(), () -> LinkBrowser.browse(e.getValue()));
}
}
else
{
fed.addButton("OSRS Twitter", () -> LinkBrowser.browse(RuneLiteProperties.getOSRSTwitterLink()));
}
fed.open();
});
return true;
}
}

View File

@@ -31,7 +31,10 @@ import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Supplier;
import javax.annotation.Nullable;
import lombok.extern.slf4j.Slf4j;
import net.runelite.http.api.RuneLiteAPI;
import okhttp3.Call;
@@ -41,7 +44,7 @@ import okhttp3.Request;
import okhttp3.Response;
@Slf4j
class RuntimeConfigLoader implements Supplier<RuntimeConfig>
public class RuntimeConfigLoader implements Supplier<RuntimeConfig>
{
private final OkHttpClient okHttpClient;
private final CompletableFuture<RuntimeConfig> configFuture;
@@ -66,6 +69,19 @@ class RuntimeConfigLoader implements Supplier<RuntimeConfig>
}
}
@Nullable
public RuntimeConfig tryGet()
{
try
{
return configFuture.get(0, TimeUnit.SECONDS);
}
catch (InterruptedException | ExecutionException | TimeoutException e)
{
return null;
}
}
private CompletableFuture<RuntimeConfig> fetch()
{
CompletableFuture<RuntimeConfig> future = new CompletableFuture<>();

View File

@@ -61,6 +61,8 @@ import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Client;
import net.runelite.client.RuneLite;
import net.runelite.client.RuneLiteProperties;
import net.runelite.client.RuntimeConfig;
import net.runelite.client.RuntimeConfigLoader;
import static net.runelite.client.rs.ClientUpdateCheckMode.AUTO;
import static net.runelite.client.rs.ClientUpdateCheckMode.NONE;
import static net.runelite.client.rs.ClientUpdateCheckMode.VANILLA;
@@ -75,7 +77,7 @@ import okhttp3.Request;
import okhttp3.Response;
@Slf4j
@SuppressWarnings("deprecation")
@SuppressWarnings({"deprecation", "removal"})
public class ClientLoader implements Supplier<Applet>
{
private static final int NUM_ATTEMPTS = 6;
@@ -87,16 +89,18 @@ public class ClientLoader implements Supplier<Applet>
private final ClientConfigLoader clientConfigLoader;
private ClientUpdateCheckMode updateCheckMode;
private final WorldSupplier worldSupplier;
private final RuntimeConfigLoader runtimeConfigLoader;
private final String javConfigUrl;
private Object client;
public ClientLoader(OkHttpClient okHttpClient, ClientUpdateCheckMode updateCheckMode, String javConfigUrl)
public ClientLoader(OkHttpClient okHttpClient, ClientUpdateCheckMode updateCheckMode, RuntimeConfigLoader runtimeConfigLoader, String javConfigUrl)
{
this.okHttpClient = okHttpClient;
this.clientConfigLoader = new ClientConfigLoader(okHttpClient);
this.updateCheckMode = updateCheckMode;
this.worldSupplier = new WorldSupplier(okHttpClient);
this.runtimeConfigLoader = runtimeConfigLoader;
this.javConfigUrl = javConfigUrl;
}
@@ -176,12 +180,19 @@ public class ClientLoader implements Supplier<Applet>
return rs;
}
catch (OutageException e)
{
return e;
}
catch (IOException | ClassNotFoundException | InstantiationException | IllegalAccessException
| VerificationException | SecurityException e)
{
log.error("Error loading RS!", e);
SwingUtilities.invokeLater(() -> FatalErrorDialog.showNetErrorWindow("loading the client", e));
if (!checkOutages())
{
SwingUtilities.invokeLater(() -> FatalErrorDialog.showNetErrorWindow("loading the client", e));
}
return e;
}
}
@@ -206,6 +217,10 @@ public class ClientLoader implements Supplier<Applet>
catch (IOException e)
{
log.info("Failed to get jav_config from host \"{}\" ({})", url.host(), e.getMessage());
if (checkOutages())
{
throw new OutageException(e);
}
if (!javConfigUrl.equals(RuneLiteProperties.getJavConfig()))
{
@@ -405,6 +420,10 @@ public class ClientLoader implements Supplier<Applet>
catch (IOException e)
{
log.warn("Failed to download gamepack from \"{}\"", url, e);
if (checkOutages())
{
throw new OutageException(e);
}
// With fallback config do 1 attempt (there are no additional urls to try)
if (!javConfigUrl.equals(RuneLiteProperties.getJavConfig()) || config.isFallback() || attempt >= NUM_ATTEMPTS)
@@ -430,6 +449,7 @@ public class ClientLoader implements Supplier<Applet>
SwingUtilities.invokeLater(() ->
new FatalErrorDialog("The client-patch is missing from the classpath. If you are building " +
"the client you need to re-run maven")
.addHelpButtons()
.addBuildingGuide()
.open());
throw new NullPointerException();
@@ -603,4 +623,22 @@ public class ClientLoader implements Supplier<Applet>
verifyJarEntry(je, chains);
}
}
private static class OutageException extends RuntimeException
{
private OutageException(Throwable cause)
{
super(cause);
}
}
private boolean checkOutages()
{
RuntimeConfig rtc = runtimeConfigLoader.tryGet();
if (rtc != null)
{
return rtc.showOutageMessage();
}
return false;
}
}

View File

@@ -137,13 +137,6 @@ public class FatalErrorDialog extends JDialog
rightColumn.setBackground(ColorScheme.DARK_GRAY_COLOR);
rightColumn.setMaximumSize(new Dimension(200, Integer.MAX_VALUE));
addButton("Open logs folder", () ->
{
LinkBrowser.open(RuneLite.LOGS_DIR.toString());
});
addButton("Get help on Discord", () -> LinkBrowser.browse(RuneLiteProperties.getDiscordInvite()));
addButton("Troubleshooting steps", () -> LinkBrowser.browse(RuneLiteProperties.getTroubleshootingLink()));
pane.add(rightColumn, BorderLayout.EAST);
}
@@ -193,6 +186,13 @@ public class FatalErrorDialog extends JDialog
return this;
}
public FatalErrorDialog addHelpButtons()
{
return addButton("Open logs folder", () -> LinkBrowser.open(RuneLite.LOGS_DIR.toString()))
.addButton("Get help on Discord", () -> LinkBrowser.browse(RuneLiteProperties.getDiscordInvite()))
.addButton("Troubleshooting steps", () -> LinkBrowser.browse(RuneLiteProperties.getTroubleshootingLink()));
}
public FatalErrorDialog addBuildingGuide()
{
return addButton("Building guide", () -> LinkBrowser.browse(RuneLiteProperties.getBuildingLink()));
@@ -205,6 +205,7 @@ public class FatalErrorDialog extends JDialog
new FatalErrorDialog("RuneLite was unable to verify the security of its connection to the internet while " +
action + ". You may have a misbehaving antivirus, internet service provider, a proxy, or an incomplete" +
" java installation.")
.addHelpButtons()
.open();
return;
}
@@ -213,6 +214,7 @@ public class FatalErrorDialog extends JDialog
{
new FatalErrorDialog("RuneLite is unable to connect to a required server while " + action + ". " +
"Please check your internet connection")
.addHelpButtons()
.open();
return;
}
@@ -222,11 +224,14 @@ public class FatalErrorDialog extends JDialog
new FatalErrorDialog("RuneLite is unable to resolve the address of a required server while " + action + ". " +
"Your DNS resolver may be misconfigured, pointing to an inaccurate resolver, or your internet connection may " +
"be down. ")
.addHelpButtons()
.addButton("Change your DNS resolver", () -> LinkBrowser.browse(RuneLiteProperties.getDNSChangeLink()))
.open();
return;
}
new FatalErrorDialog("RuneLite encountered a fatal error while " + action + ".").open();
new FatalErrorDialog("RuneLite encountered a fatal error while " + action + ".")
.addHelpButtons()
.open();
}
}

View File

@@ -19,4 +19,5 @@ runelite.api.base=https://api.runelite.net/runelite-${project.version}
runelite.session=https://api.runelite.net/session
runelite.static.base=https://static.runelite.net
runelite.ws=https://api.runelite.net/ws
runelite.config=https://static.runelite.net/config.json
runelite.config=https://static.runelite.net/config.json
runelite.osrstwitter.link=https://twitter.com/OldSchoolRS