aboutsummaryrefslogtreecommitdiff
path: root/loader/src
diff options
context:
space:
mode:
authorsyeyoung <cyoung06@naver.com>2022-11-16 00:52:17 +0900
committersyeyoung <cyoung06@naver.com>2022-11-16 00:53:02 +0900
commit3708965c0c22c216336f8aa28158ba22bfc03b60 (patch)
tree044ee0adf4fc0a4d6992be49a92b8cb55d22e75e /loader/src
parenta69263eec946558a71bee38e53f74f032c1799c2 (diff)
downloadSkyblock-Dungeons-Guide-3708965c0c22c216336f8aa28158ba22bfc03b60.tar.gz
Skyblock-Dungeons-Guide-3708965c0c22c216336f8aa28158ba22bfc03b60.tar.bz2
Skyblock-Dungeons-Guide-3708965c0c22c216336f8aa28158ba22bfc03b60.zip
- Better Exception Handling
Signed-off-by: syeyoung <cyoung06@naver.com>
Diffstat (limited to 'loader/src')
-rwxr-xr-xloader/src/main/java/kr/syeyoung/dungeonsguide/launcher/Main.java104
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/auth/AuthManager.java23
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/exceptions/AuthFailedExeption.java2
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/exceptions/AuthServerException.java2
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/exceptions/AuthenticationUnavailableException.java12
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/exceptions/PrivacyPolicyRequiredException.java2
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/exceptions/TokenExpiredException.java2
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/screen/GuiDisplayer.java44
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/screen/GuiLoadingError.java (renamed from loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/GuiLoadingError.java)12
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/screen/GuiPrivacyPolicy.java (renamed from loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/GuiPrivacyPolicy.java)14
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/screen/GuiReferenceLeak.java90
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/screen/SpecialGuiScreen.java17
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/loader/RemoteLoader.java55
13 files changed, 272 insertions, 107 deletions
diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/Main.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/Main.java
index efba137d..0ec65780 100755
--- a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/Main.java
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/Main.java
@@ -18,24 +18,18 @@
package kr.syeyoung.dungeonsguide.launcher;
-import com.mojang.authlib.exceptions.AuthenticationUnavailableException;
-import com.mojang.authlib.exceptions.InvalidCredentialsException;
import kr.syeyoung.dungeonsguide.launcher.auth.AuthManager;
-import kr.syeyoung.dungeonsguide.launcher.exceptions.AuthServerException;
import kr.syeyoung.dungeonsguide.launcher.exceptions.NoSuitableLoaderFoundException;
-import kr.syeyoung.dungeonsguide.launcher.exceptions.PrivacyPolicyRequiredException;
import kr.syeyoung.dungeonsguide.launcher.exceptions.ReferenceLeakedException;
-import kr.syeyoung.dungeonsguide.launcher.exceptions.TokenExpiredException;
-import kr.syeyoung.dungeonsguide.launcher.gui.GuiLoadingError;
-import kr.syeyoung.dungeonsguide.launcher.gui.GuiPrivacyPolicy;
+import kr.syeyoung.dungeonsguide.launcher.gui.screen.GuiDisplayer;
+import kr.syeyoung.dungeonsguide.launcher.gui.screen.GuiLoadingError;
+import kr.syeyoung.dungeonsguide.launcher.gui.screen.GuiReferenceLeak;
+import kr.syeyoung.dungeonsguide.launcher.gui.screen.SpecialGuiScreen;
import kr.syeyoung.dungeonsguide.launcher.loader.IDGLoader;
import kr.syeyoung.dungeonsguide.launcher.loader.JarLoader;
import kr.syeyoung.dungeonsguide.launcher.loader.LocalLoader;
import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiMainMenu;
-import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.resources.IReloadableResourceManager;
-import net.minecraftforge.client.event.GuiOpenEvent;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.config.Configuration;
import net.minecraftforge.fml.common.Mod;
@@ -43,13 +37,9 @@ import net.minecraftforge.fml.common.Mod.EventHandler;
import net.minecraftforge.fml.common.ProgressManager;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
-import net.minecraftforge.fml.common.eventhandler.EventPriority;
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import java.io.*;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
+import java.util.*;
@Mod(modid = Main.MOD_ID, version = Main.VERSION)
public class Main
@@ -78,28 +68,18 @@ public class Main
}
private IDGLoader currentLoader;
-
- private Throwable lastError;
- private boolean isMcLoaded;
-
-
-
-
@EventHandler
- public void initEvent(FMLInitializationEvent initializationEvent)
- {
+ public void initEvent(FMLInitializationEvent initializationEvent) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
MinecraftForge.EVENT_BUS.register(this);
- if (dgInterface != null) {
- try {
- dgInterface.init(configDir);
+ MinecraftForge.EVENT_BUS.register(GuiDisplayer.INSTANCE);
- for (DungeonsGuideReloadListener listener : listeners) {
- listener.onLoad(dgInterface);
- }
- } catch (Exception e) {
- e.printStackTrace();
- setLastFatalError(e);
- }
+ try {
+ File f = new File(configDir, "loader.cfg");
+ Configuration configuration = new Configuration(f);
+ IDGLoader idgLoader = obtainLoader(configuration);
+ load(idgLoader);
+ } catch (Throwable e) {
+ GuiDisplayer.INSTANCE.displayGui(obtainErrorGUI(e));
}
}
@@ -117,7 +97,9 @@ public class Main
currentLoader = null;
}
private void load(IDGLoader newLoader) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
- partialLoad(newLoader);
+ if (dgInterface != null) throw new IllegalStateException("DG is loaded");
+ dgInterface = newLoader.loadDungeonsGuide();
+ currentLoader = newLoader;
dgInterface.init(configDir);
@@ -125,12 +107,6 @@ public class Main
listener.onLoad(dgInterface);
}
}
- private void partialLoad(IDGLoader newLoader) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
- if (dgInterface != null) throw new IllegalStateException("DG is loaded");
- dgInterface = newLoader.loadDungeonsGuide();
- currentLoader = newLoader;
- }
-
public void reload(IDGLoader newLoader) {
try {
unload();
@@ -140,49 +116,25 @@ public class Main
currentLoader = null;
e.printStackTrace();
- setLastFatalError(e);
- }
- }
- public void tryOpenError() {
- if (isMcLoaded) Minecraft.getMinecraft().displayGuiScreen(obtainErrorGUI());
+ GuiDisplayer.INSTANCE.displayGui(obtainErrorGUI(e));
+ }
}
- public GuiScreen obtainErrorGUI() {
- if (lastError instanceof PrivacyPolicyRequiredException) {
- return new GuiPrivacyPolicy();
- } else if (lastError instanceof TokenExpiredException) {
-
+ public SpecialGuiScreen obtainErrorGUI(Throwable lastError) {
+ if (lastError instanceof kr.syeyoung.dungeonsguide.launcher.exceptions.AuthenticationUnavailableException) {
+ return null;
} else if (lastError instanceof NoSuitableLoaderFoundException) {
-
+ return new GuiLoadingError(lastError);
} else if (lastError instanceof ReferenceLeakedException) {
-
- } else if (lastError instanceof AuthServerException) {
-
- } else if (lastError instanceof InvalidCredentialsException) {
-
- } else if (lastError instanceof AuthenticationUnavailableException) {
-
+ return new GuiReferenceLeak(lastError);
} else if (lastError != null){
- return new GuiLoadingError(lastError, () -> {lastError = null;});
+ return new GuiLoadingError(lastError);
}
- if (lastError != null)
- lastError.printStackTrace();
// when gets called init and stuff remove thing
return null;
}
- @SubscribeEvent(priority = EventPriority.LOWEST)
- public void onGuiOpen(GuiOpenEvent guiOpenEvent) {
- if (guiOpenEvent.gui instanceof GuiMainMenu) {
- isMcLoaded = true;
- }
- if (lastError != null && guiOpenEvent.gui instanceof GuiMainMenu) {
- GuiScreen gui = obtainErrorGUI();
- if (gui != null)
- guiOpenEvent.gui = gui;
- }
- }
public String getLoaderName(Configuration configuration) {
String loader = System.getProperty("dg.loader");
@@ -236,7 +188,6 @@ public class Main
currentLoader = null;
t.printStackTrace();
- setLastFatalError(t);
} finally {
while(bar.getStep() < bar.getSteps()) bar.step("");
ProgressManager.pop(bar);
@@ -247,11 +198,6 @@ public class Main
});
}
- public void setLastFatalError(Throwable t) {
- lastError = t;
- tryOpenError();
- }
-
public static Main getMain() {
return main;
}
diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/auth/AuthManager.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/auth/AuthManager.java
index 5aa6962b..1613e687 100644
--- a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/auth/AuthManager.java
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/auth/AuthManager.java
@@ -2,12 +2,13 @@ package kr.syeyoung.dungeonsguide.launcher.auth;
import com.google.common.base.Throwables;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
-import com.google.gson.JsonObject;
import com.mojang.authlib.exceptions.AuthenticationException;
import kr.syeyoung.dungeonsguide.launcher.auth.token.*;
import kr.syeyoung.dungeonsguide.launcher.events.AuthChangedEvent;
import kr.syeyoung.dungeonsguide.launcher.exceptions.AuthFailedExeption;
import kr.syeyoung.dungeonsguide.launcher.exceptions.PrivacyPolicyRequiredException;
+import kr.syeyoung.dungeonsguide.launcher.gui.screen.GuiDisplayer;
+import kr.syeyoung.dungeonsguide.launcher.gui.screen.GuiPrivacyPolicy;
import lombok.Setter;
import net.minecraft.client.Minecraft;
import net.minecraftforge.common.MinecraftForge;
@@ -19,10 +20,8 @@ import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.IOException;
import java.security.InvalidKeyException;
-import java.security.KeyPair;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
-import java.util.Objects;
import java.util.concurrent.*;
@@ -49,16 +48,23 @@ public class AuthManager {
else return null;
}
+ public String getWorkingTokenOrThrow() {
+ if (currentToken instanceof DGAuthToken) return currentToken.getToken();
+ else if (currentToken instanceof FailedAuthToken) throw new AuthFailedExeption(((FailedAuthToken) currentToken).getException());
+ else if (currentToken instanceof NullToken) throw new IllegalStateException("No Token");
+ else if (currentToken instanceof PrivacyPolicyRequiredToken) throw new PrivacyPolicyRequiredException();
+ throw new IllegalStateException("weird token: "+currentToken);
+ }
+
private volatile boolean initlock = false;
public void init() {
if (initlock) {
logger.info("Cannot init AuthManger twice");
- return;
+ throw new IllegalStateException("Can not init AuthManager twice");
}
-
initlock = true;
ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("DgAuth Pool").build();
@@ -85,7 +91,7 @@ public class AuthManager {
AuthToken reAuth() {
if (reauthLock) {
- while(reauthLock);
+ while (reauthLock) ;
return currentToken;
}
@@ -97,7 +103,10 @@ public class AuthManager {
currentToken = DgAuthUtil.verifyAuth(token, encSecret, baseserverurl);
MinecraftForge.EVENT_BUS.post(new AuthChangedEvent(currentToken));
- if (currentToken instanceof PrivacyPolicyRequiredToken) throw new PrivacyPolicyRequiredException();
+ if (currentToken instanceof PrivacyPolicyRequiredToken) {
+ GuiDisplayer.INSTANCE.displayGui(new GuiPrivacyPolicy());
+ throw new PrivacyPolicyRequiredException();
+ }
} catch (NoSuchAlgorithmException | AuthenticationException | IOException | NoSuchPaddingException |
InvalidKeyException | InvalidKeySpecException | IllegalBlockSizeException | BadPaddingException e) {
currentToken = new FailedAuthToken(e);
diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/exceptions/AuthFailedExeption.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/exceptions/AuthFailedExeption.java
index 881f7a1e..d860afb6 100644
--- a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/exceptions/AuthFailedExeption.java
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/exceptions/AuthFailedExeption.java
@@ -1,6 +1,6 @@
package kr.syeyoung.dungeonsguide.launcher.exceptions;
-public class AuthFailedExeption extends RuntimeException {
+public class AuthFailedExeption extends AuthenticationUnavailableException {
public AuthFailedExeption(Throwable cause) {
super(cause);
}
diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/exceptions/AuthServerException.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/exceptions/AuthServerException.java
index 1c7a44af..67647b9b 100644
--- a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/exceptions/AuthServerException.java
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/exceptions/AuthServerException.java
@@ -24,7 +24,7 @@ import org.json.JSONObject;
import java.util.Objects;
-public class AuthServerException extends RuntimeException {
+public class AuthServerException extends AuthenticationUnavailableException {
private DGResponse response;
public AuthServerException(DGResponse response) {
diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/exceptions/AuthenticationUnavailableException.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/exceptions/AuthenticationUnavailableException.java
new file mode 100644
index 00000000..a42ddd93
--- /dev/null
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/exceptions/AuthenticationUnavailableException.java
@@ -0,0 +1,12 @@
+package kr.syeyoung.dungeonsguide.launcher.exceptions;
+
+public class AuthenticationUnavailableException extends RuntimeException {
+ public AuthenticationUnavailableException(Throwable cause){
+ super(cause);
+ }
+
+ public AuthenticationUnavailableException(String s) {
+ super(s);
+ }
+ public AuthenticationUnavailableException() {}
+}
diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/exceptions/PrivacyPolicyRequiredException.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/exceptions/PrivacyPolicyRequiredException.java
index 006e03ca..a48632dc 100644
--- a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/exceptions/PrivacyPolicyRequiredException.java
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/exceptions/PrivacyPolicyRequiredException.java
@@ -18,5 +18,5 @@
package kr.syeyoung.dungeonsguide.launcher.exceptions;
-public class PrivacyPolicyRequiredException extends RuntimeException{
+public class PrivacyPolicyRequiredException extends AuthenticationUnavailableException {
}
diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/exceptions/TokenExpiredException.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/exceptions/TokenExpiredException.java
index 2c115e2f..4826b1ba 100644
--- a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/exceptions/TokenExpiredException.java
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/exceptions/TokenExpiredException.java
@@ -18,7 +18,7 @@
package kr.syeyoung.dungeonsguide.launcher.exceptions;
-public class TokenExpiredException extends RuntimeException{
+public class TokenExpiredException extends AuthenticationUnavailableException {
public TokenExpiredException(Throwable parent) {
super(parent);
diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/screen/GuiDisplayer.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/screen/GuiDisplayer.java
new file mode 100644
index 00000000..ab772e5d
--- /dev/null
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/screen/GuiDisplayer.java
@@ -0,0 +1,44 @@
+package kr.syeyoung.dungeonsguide.launcher.gui.screen;
+
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.GuiMainMenu;
+import net.minecraftforge.client.event.GuiOpenEvent;
+import net.minecraftforge.fml.common.eventhandler.EventPriority;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+
+import java.util.LinkedList;
+import java.util.Queue;
+
+public class GuiDisplayer {
+ public static GuiDisplayer INSTANCE = new GuiDisplayer();
+ private GuiDisplayer() {}
+
+ private Queue<SpecialGuiScreen> guiScreensToShow = new LinkedList<>();
+ private boolean isMcLoaded;
+
+
+ @SubscribeEvent(priority = EventPriority.LOWEST)
+ public void onGuiOpen(GuiOpenEvent guiOpenEvent) {
+ if (guiOpenEvent.gui instanceof GuiMainMenu) {
+ isMcLoaded = true;
+ }
+ if (guiScreensToShow.size() > 0 && guiOpenEvent.gui != guiScreensToShow.peek()) {
+ SpecialGuiScreen gui = guiScreensToShow.peek();
+ if (gui == null) return;
+ gui.setOnDismiss(guiScreensToShow::poll);
+ guiOpenEvent.gui = gui;
+ }
+ }
+
+ public void displayGui(SpecialGuiScreen specialGuiScreen) {
+ if (specialGuiScreen == null) return;
+ if (!guiScreensToShow.contains(specialGuiScreen))
+ guiScreensToShow.add(specialGuiScreen);
+ if (isMcLoaded) {
+ SpecialGuiScreen gui = guiScreensToShow.peek();
+ if (gui == null) return;
+ gui.setOnDismiss(guiScreensToShow::poll);
+ Minecraft.getMinecraft().displayGuiScreen(gui);
+ }
+ }
+}
diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/GuiLoadingError.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/screen/GuiLoadingError.java
index f699b1d7..436d5d8c 100644
--- a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/GuiLoadingError.java
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/screen/GuiLoadingError.java
@@ -16,7 +16,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-package kr.syeyoung.dungeonsguide.launcher.gui;
+package kr.syeyoung.dungeonsguide.launcher.gui.screen;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.*;
@@ -27,18 +27,14 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
-public class GuiLoadingError extends GuiScreen {
- static Throwable cause;
+public class GuiLoadingError extends SpecialGuiScreen {
private final String stacktrace;
- private final GuiScreen originalGUI;
- public GuiLoadingError(GuiScreen originalGUI) {
+ public GuiLoadingError(Throwable cause) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
PrintStream printStream = new PrintStream(byteArrayOutputStream);
cause.printStackTrace(printStream);
this.stacktrace = byteArrayOutputStream.toString();
-
- this.originalGUI = originalGUI;
}
@Override
@@ -54,7 +50,7 @@ public class GuiLoadingError extends GuiScreen {
if (button.id == 0) {
FMLCommonHandler.instance().exitJava(-1,true);
} else if (button.id == 1) {
- Minecraft.getMinecraft().displayGuiScreen(originalGUI);
+ dismiss();
}
}
diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/GuiPrivacyPolicy.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/screen/GuiPrivacyPolicy.java
index b7d21b16..f7acb18a 100644
--- a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/GuiPrivacyPolicy.java
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/screen/GuiPrivacyPolicy.java
@@ -1,17 +1,12 @@
-package kr.syeyoung.dungeonsguide.launcher.gui;
+package kr.syeyoung.dungeonsguide.launcher.gui.screen;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.*;
-import net.minecraft.client.renderer.GlStateManager;
-import net.minecraft.client.renderer.Tessellator;
-import net.minecraft.client.renderer.WorldRenderer;
-import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
-import net.minecraftforge.fml.common.FMLCommonHandler;
import org.lwjgl.opengl.GL11;
import java.io.IOException;
-public class GuiPrivacyPolicy extends GuiScreen {
+public class GuiPrivacyPolicy extends SpecialGuiScreen {
@Override
public void initGui() {
ScaledResolution sr = new ScaledResolution(Minecraft.getMinecraft());
@@ -25,8 +20,9 @@ public class GuiPrivacyPolicy extends GuiScreen {
super.actionPerformed(button);
if (button.id == 0) {
// accept
+ dismiss();
} else if (button.id == 1) {
- Minecraft.getMinecraft().displayGuiScreen(null);
+ dismiss();
}
}
@@ -38,7 +34,7 @@ public class GuiPrivacyPolicy extends GuiScreen {
ScaledResolution sr = new ScaledResolution(Minecraft.getMinecraft());
FontRenderer fontRenderer = Minecraft.getMinecraft().fontRendererObj;
- fontRenderer.drawString("", (sr.getScaledWidth()-fontRenderer.getStringWidth("Please accept or deny Dungeons Guide Privacy Policy to continue"))/2,40,0xFFFF0000);
+ fontRenderer.drawString("Please accept or deny Dungeons Guide Privacy Policy to continue", (sr.getScaledWidth()-fontRenderer.getStringWidth("Please accept or deny Dungeons Guide Privacy Policy to continue"))/2,40,0xFFFF0000);
super.drawScreen(mouseX, mouseY, partialTicks);
diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/screen/GuiReferenceLeak.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/screen/GuiReferenceLeak.java
new file mode 100644
index 00000000..9c0a5980
--- /dev/null
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/screen/GuiReferenceLeak.java
@@ -0,0 +1,90 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.launcher.gui.screen;
+
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.FontRenderer;
+import net.minecraft.client.gui.Gui;
+import net.minecraft.client.gui.GuiButton;
+import net.minecraft.client.gui.ScaledResolution;
+import net.minecraftforge.fml.common.FMLCommonHandler;
+import org.lwjgl.opengl.GL11;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+
+public class GuiReferenceLeak extends SpecialGuiScreen {
+ private final String stacktrace;
+ public GuiReferenceLeak(Throwable cause) {
+
+ ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+ PrintStream printStream = new PrintStream(byteArrayOutputStream);
+ cause.printStackTrace(printStream);
+ this.stacktrace = byteArrayOutputStream.toString();
+ }
+
+ @Override
+ public void initGui() {
+ ScaledResolution sr = new ScaledResolution(Minecraft.getMinecraft());
+ this.buttonList.add(new GuiButton(0, sr.getScaledWidth()/2-100,sr.getScaledHeight()-70 ,"Close Minecraft"));
+ this.buttonList.add(new GuiButton(1, sr.getScaledWidth()/2-100,sr.getScaledHeight()-40 ,"Play With DG in Inconsistent State"));
+ }
+
+ @Override
+ protected void actionPerformed(GuiButton button) throws IOException {
+ super.actionPerformed(button);
+ if (button.id == 0) {
+ FMLCommonHandler.instance().exitJava(-1,true);
+ } else if (button.id == 1) {
+ dismiss();
+ }
+ }
+
+ @Override
+ public void drawScreen(int mouseX, int mouseY, float partialTicks) {
+ super.drawBackground(1);
+
+ ScaledResolution sr = new ScaledResolution(Minecraft.getMinecraft());
+ FontRenderer fontRenderer = Minecraft.getMinecraft().fontRendererObj;
+ fontRenderer.drawString("DungeonsGuide has ran into error while reloading", (sr.getScaledWidth()-fontRenderer.getStringWidth("DungeonsGuide has ran into error while reloading"))/2,40,0xFFFF0000);
+ fontRenderer.drawString("Please contact DungeonsGuide support with this screen", (sr.getScaledWidth()-fontRenderer.getStringWidth("Please contact developer with this screen"))/2, (int) (40+fontRenderer.FONT_HEIGHT*1.5),0xFFFF0000);
+ fontRenderer.drawString("Playing in this state is VERY UNSUGGESTED. Undesired behaviors might occur.", (sr.getScaledWidth()-fontRenderer.getStringWidth("Playing in this state is VERY UNSUGGESTED. Undesired behaviors might occur."))/2, (int) (40+fontRenderer.FONT_HEIGHT*3),0xFFFF0000);
+
+ int tenth = sr.getScaledWidth() / 10;
+
+ Gui.drawRect(tenth, 90,sr.getScaledWidth()-tenth, sr.getScaledHeight()-80, 0xFF5B5B5B);
+ String[] split = stacktrace.split("\n");
+ clip(sr, tenth, 90,sr.getScaledWidth()-2*tenth, sr.getScaledHeight()-150);
+ GL11.glEnable(GL11.GL_SCISSOR_TEST);
+ for (int i = 0; i < split.length; i++) {
+ fontRenderer.drawString(split[i].replace("\t", " "), tenth+2,i*fontRenderer.FONT_HEIGHT + 92, 0xFFFFFFFF);
+ }
+ GL11.glDisable(GL11.GL_SCISSOR_TEST);
+
+ super.drawScreen(mouseX, mouseY, partialTicks);
+ }
+
+ public static void clip(ScaledResolution resolution, int x, int y, int width, int height) {
+ if (width < 0 || height < 0) return;
+
+ int scale = resolution.getScaleFactor();
+ GL11.glScissor((x ) * scale, Minecraft.getMinecraft().displayHeight - (y + height) * scale, (width) * scale, height * scale);
+ }
+}
diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/screen/SpecialGuiScreen.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/screen/SpecialGuiScreen.java
new file mode 100644
index 00000000..0a9f2602
--- /dev/null
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/screen/SpecialGuiScreen.java
@@ -0,0 +1,17 @@
+package kr.syeyoung.dungeonsguide.launcher.gui.screen;
+
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.GuiScreen;
+
+public abstract class SpecialGuiScreen extends GuiScreen {
+
+ private Runnable onDismiss;
+ public void setOnDismiss(Runnable dismissed) {
+ this.onDismiss = dismissed;
+ }
+
+ protected void dismiss() {
+ onDismiss.run();
+ Minecraft.getMinecraft().displayGuiScreen(null);
+ }
+}
diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/loader/RemoteLoader.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/loader/RemoteLoader.java
index f3baaa9d..98155245 100644
--- a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/loader/RemoteLoader.java
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/loader/RemoteLoader.java
@@ -3,10 +3,65 @@ package kr.syeyoung.dungeonsguide.launcher.loader;
import kr.syeyoung.dungeonsguide.launcher.DGInterface;
import kr.syeyoung.dungeonsguide.launcher.exceptions.ReferenceLeakedException;
+import java.lang.ref.PhantomReference;
+import java.lang.ref.ReferenceQueue;
+import java.net.URL;
+import java.net.URLClassLoader;
+
public class RemoteLoader implements IDGLoader {
private String branch;
private String version;
+
+ private ReferenceQueue<ClassLoader> refQueue = new ReferenceQueue<>();
+ private PhantomReference<ClassLoader> phantomReference;
+
+ private boolean loaded;
+
+ public static class JarClassLoader extends URLClassLoader {
+ public JarClassLoader(URL[] urls, ClassLoader parent) {
+ super(urls, parent);
+ }
+
+ @Override
+ protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
+
+ synchronized (getClassLoadingLock(name)) {
+ Class<?> c = findLoadedClass(name);
+ if (c == null) {
+
+ try {
+ if (c == null) {
+ long t0 = System.nanoTime();
+ c = findClass(name);
+
+ sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t0);
+ sun.misc.PerfCounter.getFindClasses().increment();
+ }
+ } catch (ClassNotFoundException e) {
+ // ClassNotFoundException thrown if class not found
+ // from the non-null parent class loader
+ }
+ if (getParent() != null && c == null) {
+ long t0 = System.nanoTime();
+ c = getParent().loadClass(name);
+ long t1 = System.nanoTime();
+ sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
+ }
+ }
+ if (resolve) {
+ resolveClass(c);
+ }
+ return c;
+ }
+ }
+
+ public Class<?> loadClassResolve(String name, boolean resolve) throws ClassNotFoundException {
+ return this.loadClass(name, resolve);
+ }
+ }
+
+ private JarLoader.JarClassLoader classLoader;
@Override
public DGInterface loadDungeonsGuide() throws InstantiationException, IllegalAccessException, ClassNotFoundException {
return null;