diff options
9 files changed, 165 insertions, 443 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 577e1eb5..36456dbc 100755 --- a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/Main.java +++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/Main.java @@ -22,8 +22,7 @@ import kr.syeyoung.dungeonsguide.launcher.auth.AuthManager; import kr.syeyoung.dungeonsguide.launcher.branch.UpdateRetrieverUtil; import kr.syeyoung.dungeonsguide.launcher.exceptions.*; import kr.syeyoung.dungeonsguide.launcher.gui.screen.GuiDisplayer; -import kr.syeyoung.dungeonsguide.launcher.gui.screen.GuiLoadingError; -import kr.syeyoung.dungeonsguide.launcher.gui.screen.GuiUnloadingError; +import kr.syeyoung.dungeonsguide.launcher.gui.screen.WidgetError; import kr.syeyoung.dungeonsguide.launcher.gui.screen.version.WidgetChooseVersion; import kr.syeyoung.dungeonsguide.launcher.gui.tooltip.Notification; import kr.syeyoung.dungeonsguide.launcher.gui.tooltip.NotificationManager; @@ -146,11 +145,11 @@ public class Main unload(); } catch (Exception e2) { e2.printStackTrace(); - GuiDisplayer.INSTANCE.displayGui(new GuiUnloadingError(e2)); + GuiDisplayer.INSTANCE.displayGui(new GuiScreenAdapter(new GlobalHUDScale(new WidgetError(e2)))); } - GuiDisplayer.INSTANCE.displayGui(new GuiLoadingError(e)); + GuiDisplayer.INSTANCE.displayGui(new GuiScreenAdapter(new GlobalHUDScale(new WidgetError(e)))); } catch (DungeonsGuideUnloadingException e) { - GuiDisplayer.INSTANCE.displayGui(new GuiUnloadingError(e)); + GuiDisplayer.INSTANCE.displayGui(new GuiScreenAdapter(new GlobalHUDScale(new WidgetError(e)))); } } @@ -211,17 +210,32 @@ public class Main } private volatile IDGLoader reqLoader = null; + private volatile boolean unload = false; public void reloadWithoutStacktraceReference(IDGLoader newLoader) { reqLoader = newLoader; } + public void unloadWithoutStacktraceReference(IDGLoader newLoader) { + unload = true; + } @SubscribeEvent public void onTick(TickEvent.ClientTickEvent tickEvent) { if (reqLoader != null) { IDGLoader loader = reqLoader; reqLoader = null; + unload = false; tryReloadingWithSplash(loader); } + if (unload) { + try { + unload(); + } catch (Exception e2) { + e2.printStackTrace(); + GuiDisplayer.INSTANCE.displayGui(new GuiScreenAdapter(new GlobalHUDScale(new WidgetError(e2)))); + } + reqLoader = null; + unload = false; + } } public void reload(IDGLoader newLoader) throws DungeonsGuideLoadingException, DungeonsGuideUnloadingException { 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 6f9a2d65..384fe5b2 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 @@ -26,7 +26,7 @@ import kr.syeyoung.dungeonsguide.launcher.exceptions.auth.AuthFailedException; import kr.syeyoung.dungeonsguide.launcher.exceptions.auth.AuthenticationUnavailableException; import kr.syeyoung.dungeonsguide.launcher.exceptions.auth.PrivacyPolicyRequiredException; import kr.syeyoung.dungeonsguide.launcher.gui.screen.GuiDisplayer; -import kr.syeyoung.dungeonsguide.launcher.gui.screen.GuiLoadingError; +import kr.syeyoung.dungeonsguide.launcher.gui.screen.WidgetError; import kr.syeyoung.dungeonsguide.launcher.gui.screen.WidgetPrivacyPolicy; import kr.syeyoung.dungeonsguide.launcher.gui.tooltip.Notification; import kr.syeyoung.dungeonsguide.launcher.gui.tooltip.NotificationManager; @@ -41,7 +41,6 @@ import org.apache.logging.log4j.Logger; import java.util.UUID; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; @@ -157,7 +156,7 @@ public class AuthManager { .description("Authentication Error Occurred\n"+e.getMessage()) .titleColor(0xFFFF0000) .onClick(() -> { - GuiDisplayer.INSTANCE.displayGui(new GuiLoadingError(e)); + GuiDisplayer.INSTANCE.displayGui(new GuiScreenAdapter(new GlobalHUDScale(new WidgetError(e)))); }) .build())); } @@ -210,7 +209,7 @@ public class AuthManager { .description("Authentication Error Occurred\n"+e.getMessage()) .titleColor(0xFFFF0000) .onClick(() -> { - GuiDisplayer.INSTANCE.displayGui(new GuiLoadingError(e)); + GuiDisplayer.INSTANCE.displayGui(new GuiScreenAdapter(new GlobalHUDScale(new WidgetError(e)))); }) .build())); } diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/screen/GuiChooseVersion.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/screen/GuiChooseVersion.java deleted file mode 100644 index e42e45dc..00000000 --- a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/screen/GuiChooseVersion.java +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod - * Copyright (C) 2022 cyoung06 (syeyoung) - * - * 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 kr.syeyoung.dungeonsguide.launcher.LoaderMeta; -import kr.syeyoung.dungeonsguide.launcher.Main; -import kr.syeyoung.dungeonsguide.launcher.branch.Update; -import kr.syeyoung.dungeonsguide.launcher.branch.UpdateBranch; -import kr.syeyoung.dungeonsguide.launcher.branch.UpdateRetrieverUtil; -import kr.syeyoung.dungeonsguide.launcher.gui.tooltip.Notification; -import kr.syeyoung.dungeonsguide.launcher.gui.tooltip.NotificationManager; -import kr.syeyoung.dungeonsguide.launcher.gui.tooltip.WidgetNotification; -import kr.syeyoung.dungeonsguide.launcher.gui.tooltip.WidgetNotificationAutoClose; -import kr.syeyoung.dungeonsguide.launcher.loader.JarLoader; -import kr.syeyoung.dungeonsguide.launcher.loader.LocalLoader; -import kr.syeyoung.dungeonsguide.launcher.loader.RemoteLoader; -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.client.config.GuiCheckBox; - -import java.awt.*; -import java.awt.datatransfer.StringSelection; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.PrintStream; -import java.util.Collections; -import java.util.List; -import java.util.Optional; -import java.util.UUID; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.stream.Collectors; - -public class GuiChooseVersion extends SpecialGuiScreen { - private static final ExecutorService executor = Executors.newSingleThreadExecutor(); - private Throwable cause; - - public GuiChooseVersion(Throwable cause) { - this.cause = cause; - - ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); - PrintStream printStream = new PrintStream(byteArrayOutputStream); - cause.printStackTrace(printStream); - this.stacktrace = byteArrayOutputStream.toString(); - - try { - fetchList(); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - private void fetchList () throws IOException { - loading.incrementAndGet(); - executor.submit(() -> { - try { - branchList = UpdateRetrieverUtil.getUpdateBranches().stream() - .filter(updateBranch -> - Optional.ofNullable(updateBranch.getMetadata()) - .filter(a -> a.has("additionalMeta")) - .map(a -> a.getJSONObject("additionalMeta")) - .filter(a -> a.has("type")) - .map(a -> a.getString("type")).orElse("").equals("mod")) - .collect(Collectors.toList()); - } catch (IOException e) { - e.printStackTrace(); - } finally { - smthUpdated = true; - loading.decrementAndGet(); - } - }); - } - - private void fetchUpdates(UpdateBranch branch) throws IOException { - loading.incrementAndGet(); - executor.submit(() -> { - try { - updates = UpdateRetrieverUtil.getLatestUpdates(branch.getId(), 0); - } catch (IOException e) { - e.printStackTrace(); - } finally { - smthUpdated = true; - loading.decrementAndGet(); - } - }); - } - private final String stacktrace; - - private List<UpdateBranch> branchList = Collections.emptyList(); - private List<Update> updates = Collections.emptyList(); - private UpdateBranch current; - private volatile boolean smthUpdated = false; - private volatile AtomicInteger loading = new AtomicInteger(0); - - private GuiCheckBox checkBox; - @Override - public void initGui() { - super.initGui(); - // Local version - // Jar embedded version - // Remote version - // dg gui lib....? - - ScaledResolution sr = new ScaledResolution(Minecraft.getMinecraft()); - this.buttonList.add(new GuiButton(2, 0,sr.getScaledHeight()-20 ,"Copy Error into Clipboard")); - - this.buttonList.add(new GuiButton(3, sr.getScaledWidth()/2-100,sr.getScaledHeight()-40 ,"Play Without DG")); - GuiButton button; - int tenth = sr.getScaledWidth()/10; - this.buttonList.add(button = new GuiButton(0, tenth,90 ,"Try loading Locally (classes)")); - button.enabled = this.getClass().getResourceAsStream("/kr/syeyoung/dungeonsguide/mod/DungeonsGuide.class") != null; - this.buttonList.add(button = new GuiButton(1, tenth,110 ,"Try loading Local Jar (embedded jar)")); - button.enabled = this.getClass().getResourceAsStream("/mod.jar") != null; - this.buttonList.add(button = new GuiButton(4, tenth,sr.getScaledHeight()-100 ,"Refresh Options")); - -// this.buttonList.add(checkBox = new GuiCheckBox(5, sr.getScaledWidth() - tenth-200,sr.getScaledHeight()-100 ,"Save This Loader", false)); - - int k = 0; - for (UpdateBranch updateBranch : branchList) { - this.buttonList.add(new GuiButton(10 + k++, tenth, 110 + 20 * k,"Remote Branch: "+ updateBranch.getName())); - } - - k = 0; - for (Update update : updates) { - this.buttonList.add(button = new GuiButton(branchList.size() + 10 + k++, tenth+210, 70+ 20 * k, update.getName())); - if (update.getMetadata().has("loaderVersion") && update.getMetadata().getInt("loaderVersion") > LoaderMeta.LOADER_VERSION) { - button.enabled = false; - } - } - } - - @Override - protected void actionPerformed(GuiButton button) throws IOException { - super.actionPerformed(button); - if (button.id == 2) { - Toolkit.getDefaultToolkit() - .getSystemClipboard() - .setContents( - new StringSelection(stacktrace), - null - ); - - UUID random = UUID.randomUUID(); - NotificationManager.getInstance().updateNotification(random, - new WidgetNotificationAutoClose(random, Notification.builder() - .title("Successfully Copied!") - .description("") - .titleColor(0xFF00FF00) - .build(), 5000L)); - } else if (button.id == 0) { - dismiss(); - Main.getMain().tryReloadingWithSplash(new LocalLoader()); - } else if (button.id == 1) { - dismiss(); - Main.getMain().tryReloadingWithSplash(new JarLoader()); - } else if (button.id == 3) { - dismiss(); - } else if (button.id == 4) { - branchList = Collections.emptyList(); - updates = Collections.emptyList(); - current = null; - smthUpdated = true; - fetchList(); -// } else if (button.id == 5) { -// // do smt - } else if (button.id < branchList.size() + 10) { - int idx = button.id - 10; - current = branchList.get(idx); - fetchUpdates(branchList.get(idx)); - } else if (button.id < branchList.size() + 10 + updates.size()){ - int idx = button.id - branchList.size() - 10; - Update update = updates.get(idx); - - dismiss(); - Main.getMain().tryReloadingWithSplash(new RemoteLoader(current.getName(),current.getId(),update.getId())); - } - } - - @Override - public void updateScreen() { - super.updateScreen(); - if (smthUpdated) { - this.buttonList.clear(); - initGui(); - smthUpdated = false; - } - } - - @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("Please choose a new version to load", (sr.getScaledWidth()-fontRenderer.getStringWidth("Please choose a new version to load"))/2,(int) (40),0xFFFF0000); - fontRenderer.drawString("Problem: "+cause.getMessage(), (sr.getScaledWidth()-fontRenderer.getStringWidth("Problem: "+cause.getMessage()))/2, (int) (40+fontRenderer.FONT_HEIGHT*1.5),0xFFFF0000); - - int tenth = sr.getScaledWidth() / 10; - Gui.drawRect(tenth, 90,sr.getScaledWidth()-tenth, sr.getScaledHeight()-80, 0xFF5B5B5B); - - if (loading.get() > 0) { - fontRenderer.drawString("Loading", sr.getScaledWidth()/2, sr.getScaledHeight()/2, 0xFF000000); - } - - super.drawScreen(mouseX, mouseY, partialTicks); - } -} diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/screen/GuiLoadingError.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/screen/GuiLoadingError.java deleted file mode 100644 index 9b8390bd..00000000 --- a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/screen/GuiLoadingError.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * 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 kr.syeyoung.dungeonsguide.launcher.gui.tooltip.Notification; -import kr.syeyoung.dungeonsguide.launcher.gui.tooltip.NotificationManager; -import kr.syeyoung.dungeonsguide.launcher.gui.tooltip.WidgetNotification; -import kr.syeyoung.dungeonsguide.launcher.gui.tooltip.WidgetNotificationAutoClose; -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.awt.*; -import java.awt.datatransfer.StringSelection; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.PrintStream; -import java.util.UUID; - -public class GuiLoadingError extends SpecialGuiScreen { - private final String stacktrace; - public GuiLoadingError(Throwable cause) { - - ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); - PrintStream printStream = new PrintStream(byteArrayOutputStream); - cause.printStackTrace(printStream); - this.stacktrace = byteArrayOutputStream.toString(); - } - - @Override - public void initGui() { - super.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 Without DG")); - this.buttonList.add(new GuiButton(2, 0,sr.getScaledHeight()-20 ,"Copy Error into Clipboard")); - } - - @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(); - } else if (button.id == 2) { - Toolkit.getDefaultToolkit() - .getSystemClipboard() - .setContents( - new StringSelection(stacktrace), - null - ); - - UUID uuid = UUID.randomUUID(); - NotificationManager.getInstance().updateNotification(uuid, new WidgetNotificationAutoClose(uuid, Notification.builder() - .title("Successfully Copied!") - .description("") - .titleColor(0xFF00FF00) - .build(), 5000L)); - } - } - - @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 loading itself", (sr.getScaledWidth()-fontRenderer.getStringWidth("DungeonsGuide has ran into error while loading itself"))/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); - - int tenth = sr.getScaledWidth() / 10; - - Gui.drawRect(tenth, 70,sr.getScaledWidth()-tenth, sr.getScaledHeight()-80, 0xFF5B5B5B); - String[] split = stacktrace.split("\n"); - clip(sr, tenth, 70,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 + 72, 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/GuiUnloadingError.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/screen/GuiUnloadingError.java deleted file mode 100644 index 523c1ce4..00000000 --- a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/screen/GuiUnloadingError.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * 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 GuiUnloadingError extends SpecialGuiScreen { - private final String stacktrace; - public GuiUnloadingError(Throwable cause) { - - ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); - PrintStream printStream = new PrintStream(byteArrayOutputStream); - cause.printStackTrace(printStream); - this.stacktrace = byteArrayOutputStream.toString(); - } - - @Override - public void initGui() { - super.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 NOT RECOMMENDED. Undesired behaviors might occur.", (sr.getScaledWidth()-fontRenderer.getStringWidth("Playing in this state is NOT RECOMMENDED. 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/WidgetError.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/screen/WidgetError.java new file mode 100644 index 00000000..0fe4b6a0 --- /dev/null +++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/screen/WidgetError.java @@ -0,0 +1,73 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2023 cyoung06 (syeyoung) + * + * 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 kr.syeyoung.dungeonsguide.launcher.gui.tooltip.Notification; +import kr.syeyoung.dungeonsguide.launcher.gui.tooltip.NotificationManager; +import kr.syeyoung.dungeonsguide.launcher.gui.tooltip.WidgetNotificationAutoClose; +import kr.syeyoung.dungeonsguide.launcher.guiv2.BindableAttribute; +import kr.syeyoung.dungeonsguide.launcher.guiv2.xml.AnnotatedImportOnlyWidget; +import kr.syeyoung.dungeonsguide.launcher.guiv2.xml.annotations.Bind; +import kr.syeyoung.dungeonsguide.launcher.guiv2.xml.annotations.On; +import net.minecraft.client.Minecraft; +import net.minecraft.client.audio.PositionedSoundRecord; +import net.minecraft.util.ResourceLocation; + +import java.awt.*; +import java.awt.datatransfer.StringSelection; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.util.UUID; + +public class WidgetError extends AnnotatedImportOnlyWidget { + @Bind(variableName = "stacktrace") + public final BindableAttribute<String> stacktrace = new BindableAttribute<>(String.class); + + public WidgetError(Throwable cause) { + super(new ResourceLocation("dungeons_guide_loader:gui/error.gui")); + + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + PrintStream printStream = new PrintStream(byteArrayOutputStream); + cause.printStackTrace(printStream); + this.stacktrace.setValue(byteArrayOutputStream.toString().replace("\t", " ")); + } + + @On(functionName = "continue") + public void exit() { + Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F)); + Minecraft.getMinecraft().displayGuiScreen(null); + } + @On(functionName = "copy") + public void copy() { + Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F)); + Toolkit.getDefaultToolkit() + .getSystemClipboard() + .setContents( + new StringSelection(stacktrace.getValue()), + null + ); + + UUID uuid = UUID.randomUUID(); + NotificationManager.getInstance().updateNotification(uuid, new WidgetNotificationAutoClose(uuid, Notification.builder() + .title("Successfully Copied!") + .description("") + .titleColor(0xFF00FF00) + .build(), 5000L)); + } +} diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/ScrollablePanel.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/ScrollablePanel.java index 523a880b..4bb125c0 100644 --- a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/ScrollablePanel.java +++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/ScrollablePanel.java @@ -121,13 +121,13 @@ public class ScrollablePanel extends AnnotatedWidget { if (direction.getValue().vertical) { double old = this.y.getValue(), neu; this.y.setValue( - neu = Layouter.clamp(this.y.getValue() + scrollAmount,0, contentHeight.getValue()) + neu = Layouter.clamp(this.y.getValue() - scrollAmount,0, contentHeight.getValue()) ); return old != neu; } else if (direction.getValue().horizontal) { double old = this.x.getValue(), neu; this.x.setValue( - neu = Layouter.clamp(this.x.getValue() + scrollAmount,0, contentWidth.getValue()) + neu = Layouter.clamp(this.x.getValue() - scrollAmount,0, contentWidth.getValue()) ); return old != neu; } diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/richtext/FlatTextSpan.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/richtext/FlatTextSpan.java index f0a93ed7..4692df8d 100644 --- a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/richtext/FlatTextSpan.java +++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/richtext/FlatTextSpan.java @@ -58,6 +58,7 @@ public class FlatTextSpan { int endIdx = value.length; boolean lineBroken = false; + boolean wasNewLine = false; for (int i = 0; i < value.length; i++) { char character = value[i]; charWidth = textStyle.getFontRenderer().getWidth(character, textStyle); @@ -83,6 +84,7 @@ public class FlatTextSpan { if (character == '\n') { endIdx = i+1; lineBroken = true; + wasNewLine = true; break; } @@ -120,7 +122,8 @@ public class FlatTextSpan { char[] second = null; if (lineBroken) { int startRealWord = -1; - for (int i = endIdx; i< value.length; i++) { + if (wasNewLine) startRealWord = endIdx; + else for (int i = endIdx; i< value.length; i++) { if (value[i] == ' ') continue; startRealWord = i; break; @@ -150,6 +153,7 @@ public class FlatTextSpan { double totalWidth = 0; double effectiveWidth = 0; boolean lineBroken =false; + boolean wasNewLine = false; int endIdx = value.length; for (int i = 0; i < value.length; i++) { @@ -162,6 +166,7 @@ public class FlatTextSpan { // Force break. endIdx = i + 1; lineBroken = true; + wasNewLine = true; break; } @@ -180,7 +185,8 @@ public class FlatTextSpan { char[] second = null; if (lineBroken) { int startRealWord = -1; - for (int i = endIdx; i< value.length; i++) { + if (wasNewLine) startRealWord = endIdx; + else for (int i = endIdx; i< value.length; i++) { if (value[i] == ' ') continue; startRealWord = i; break; diff --git a/loader/src/main/resources/assets/dungeons_guide_loader/gui/error.gui b/loader/src/main/resources/assets/dungeons_guide_loader/gui/error.gui new file mode 100644 index 00000000..b99946b3 --- /dev/null +++ b/loader/src/main/resources/assets/dungeons_guide_loader/gui/error.gui @@ -0,0 +1,60 @@ +<!-- + ~ Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + ~ Copyright (C) 2023 cyoung06 (syeyoung) + ~ + ~ 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/>. + --> + +<bgcolor backgroundColor="#FF111111"> + <stack> + <align hAlign="START" vAlign="END"> + <size width="100" height="20"> + <RoundButton text="Copy Log" on:click="copy"/> + </size> + </align> + <align vAlign="CENTER"> + <ConstrainedBox maxHeight="450"> + <col crossAlign="CENTER"> + <size width="0" height="10"/> + <Text text="Dungeons Guide has ran into error while loading or unloading" color="#FFFFFFFF"/> + <size width="0" height="10"/> + <flexible> + <align hAlign="CENTER"> + <padding left="10" right="10"> + <border> + <line slot="left" dir="VERTICAL" thickness="1.0" color="#FFFFFFFF"/> + <line slot="top" dir="HORIZONTAL" thickness="1.0" color="#FFFFFFFF"/> + <line slot="bottom" dir="HORIZONTAL" thickness="1.0" color="#FFFFFFFF"/> + <line slot="right" dir="VERTICAL" thickness="1.0" color="#FFFFFFFF"/> + <ConstrainedBox maxWidth="600" slot="content"> + <bgcolor backgroundColor="#FF222222"> + <ScrollablePanel> + <Text bind:text="stacktrace" color="#FFFFFFFF"/> + </ScrollablePanel> + </bgcolor> + </ConstrainedBox> + </border> + </padding> + </align> + </flexible> + <size width="0" height="15"/> + <size width="100" height="20"> + <RoundButton text="Continue" on:click="continue"/> + </size> + <size width="0" height="10"/> + </col> + </ConstrainedBox> + </align> + </stack> +</bgcolor>
\ No newline at end of file |