aboutsummaryrefslogtreecommitdiff
path: root/loader
diff options
context:
space:
mode:
Diffstat (limited to 'loader')
-rwxr-xr-xloader/src/main/java/kr/syeyoung/dungeonsguide/launcher/Main.java21
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/auth/AuthManager.java25
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/screen/GuiChooseVersion.java7
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/screen/GuiLoadingError.java6
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/tooltip/NotificationManager.java363
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/tooltip/NotificationManagerRootWidget.java56
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/tooltip/WidgetNotification.java64
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/tooltip/WidgetNotificationAutoClose.java86
-rw-r--r--loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/Text.java1
-rw-r--r--loader/src/main/resources/assets/dungeons_guide_loader/gui/fi0
-rw-r--r--loader/src/main/resources/assets/dungeons_guide_loader/gui/tooltips/tooltip.gui48
-rw-r--r--loader/src/main/resources/assets/dungeons_guide_loader/gui/tooltips/tooltipClosing.gui63
-rw-r--r--loader/src/main/resources/assets/dungeons_guide_loader/gui/tooltips/tooltipHolder.gui6
13 files changed, 574 insertions, 172 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 b4d9622a..42d5244d 100755
--- a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/Main.java
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/Main.java
@@ -30,6 +30,9 @@ import kr.syeyoung.dungeonsguide.launcher.gui.screen.GuiLoadingError;
import kr.syeyoung.dungeonsguide.launcher.gui.screen.GuiUnloadingError;
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.guiv2.elements.richtext.fonts.DefaultFontRenderer;
import kr.syeyoung.dungeonsguide.launcher.loader.*;
import kr.syeyoung.dungeonsguide.launcher.util.ProgressStateHolder;
import lombok.Getter;
@@ -92,9 +95,9 @@ public class Main
public void initEvent(FMLInitializationEvent initializationEvent) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
MinecraftForge.EVENT_BUS.register(this);
MinecraftForge.EVENT_BUS.register(GuiDisplayer.INSTANCE);
- MinecraftForge.EVENT_BUS.register(NotificationManager.INSTANCE);
+ MinecraftForge.EVENT_BUS.register(NotificationManager.getEventHandler());
- NotificationManager.INSTANCE.updateNotification(dgUnloaded, Notification.builder()
+ NotificationManager.getInstance().updateNotification(dgUnloaded, new WidgetNotification(dgUnloaded, Notification.builder()
.title("Dungeons Guide Not Loaded")
.titleColor(0xFFFF0000)
.description("Click to try reloading....")
@@ -102,7 +105,7 @@ public class Main
GuiDisplayer.INSTANCE.displayGui(new GuiChooseVersion(new RuntimeException("just unloaded")));
})
.unremovable(true)
- .build());
+ .build()));
try {
File f = new File(configDir, "loader.cfg");
@@ -159,7 +162,7 @@ public class Main
listener.unloadReference();
}
- NotificationManager.INSTANCE.updateNotification(dgUnloaded, Notification.builder()
+ NotificationManager.getInstance().updateNotification(dgUnloaded, new WidgetNotification(dgUnloaded, Notification.builder()
.title("Dungeons Guide Not Loaded")
.titleColor(0xFFFF0000)
.description("Click to try reloading....")
@@ -167,7 +170,7 @@ public class Main
GuiDisplayer.INSTANCE.displayGui(new GuiChooseVersion(new RuntimeException("just unloaded")));
})
.unremovable(true)
- .build());
+ .build()));
if (currentLoader != null) {
currentLoader.unloadDungeonsGuide();
}
@@ -188,15 +191,16 @@ public class Main
listener.onLoad(dgInterface);
}
+ UUID uid = UUID.randomUUID();
- NotificationManager.INSTANCE.updateNotification(UUID.randomUUID(), Notification.builder()
+ NotificationManager.getInstance().updateNotification(uid, new WidgetNotificationAutoClose(uid, Notification.builder()
.title("Dungeons Guide Loaded!")
.description("Successfully Loaded Dungeons Guide!\nLoader: "+currentLoader.loaderName()+"\nVersion: "+currentLoader.version())
.titleColor(0xFF00FF00)
- .build());
+ .build(), 10000L));
- NotificationManager.INSTANCE.removeNotification(dgUnloaded);
+ NotificationManager.getInstance().removeNotification(dgUnloaded);
}
private volatile IDGLoader reqLoader = null;
@@ -301,6 +305,7 @@ public class Main
((IReloadableResourceManager) Minecraft.getMinecraft().getResourceManager()).registerReloadListener(a -> {
if (dgInterface != null) dgInterface.onResourceReload(a);
+ DefaultFontRenderer.DEFAULT_RENDERER.onResourceManagerReload();
});
}
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 f582ba6f..6c8fa7bc 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
@@ -30,6 +30,7 @@ import kr.syeyoung.dungeonsguide.launcher.gui.screen.GuiLoadingError;
import kr.syeyoung.dungeonsguide.launcher.gui.screen.GuiPrivacyPolicy;
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 net.minecraft.client.Minecraft;
import net.minecraftforge.common.MinecraftForge;
import org.apache.logging.log4j.LogManager;
@@ -135,11 +136,11 @@ public class AuthManager {
}
- NotificationManager.INSTANCE.removeNotification(authenticationFailure);
- NotificationManager.INSTANCE.removeNotification(privacyPolicyRequired);
+ NotificationManager.getInstance().removeNotification(authenticationFailure);
+ NotificationManager.getInstance().removeNotification(privacyPolicyRequired);
} catch (Exception e) {
if (e instanceof PrivacyPolicyRequiredException) {
- NotificationManager.INSTANCE.updateNotification(privacyPolicyRequired, Notification.builder()
+ NotificationManager.getInstance().updateNotification(privacyPolicyRequired, new WidgetNotification(privacyPolicyRequired, Notification.builder()
.title("Privacy Policy")
.description("Please accept Dungeons Guide\nPrivacy Policy to enjoy server based\nfeatures of Dungeons Guide\n\n(Including Auto-Update/Remote-Jar)")
.titleColor(0xFFFF0000)
@@ -147,10 +148,10 @@ public class AuthManager {
.onClick(() -> {
GuiDisplayer.INSTANCE.displayGui(new GuiPrivacyPolicy());
})
- .build());
+ .build()));
} else {
currentToken = new FailedAuthToken(e);
- NotificationManager.INSTANCE.updateNotification(authenticationFailure, Notification.builder()
+ NotificationManager.getInstance().updateNotification(authenticationFailure, new WidgetNotification(authenticationFailure, Notification.builder()
.title("Auth Error")
.description("Authentication Error Occurred\n"+e.getMessage())
.titleColor(0xFFFF0000)
@@ -158,7 +159,7 @@ public class AuthManager {
.onClick(() -> {
GuiDisplayer.INSTANCE.displayGui(new GuiLoadingError(e));
})
- .build());
+ .build()));
}
logger.error("Re-auth failed with message {}, trying again in a 2 seconds", String.valueOf(Throwables.getRootCause(e)));
throw new AuthFailedException(e);
@@ -177,14 +178,14 @@ public class AuthManager {
if (currentToken instanceof PrivacyPolicyRequiredToken) {
reauthLock = true;
- NotificationManager.INSTANCE.removeNotification(authenticationFailure);
- NotificationManager.INSTANCE.removeNotification(privacyPolicyRequired);
+ NotificationManager.getInstance().removeNotification(authenticationFailure);
+ NotificationManager.getInstance().removeNotification(privacyPolicyRequired);
try {
currentToken = DgAuthUtil.acceptNewPrivacyPolicy(currentToken.getToken(), version);
if (currentToken instanceof PrivacyPolicyRequiredToken) throw new PrivacyPolicyRequiredException();
} catch (Exception e) {
if (e instanceof PrivacyPolicyRequiredException) {
- NotificationManager.INSTANCE.updateNotification(privacyPolicyRequired, Notification.builder()
+ NotificationManager.getInstance().updateNotification(privacyPolicyRequired, new WidgetNotification(privacyPolicyRequired, Notification.builder()
.title("Privacy Policy")
.description("Please accept the Dungeons Guide\nPrivacy Policy to enjoy server based\nfeatures of Dungeons Guide\n\n(Including Auto-Update/Remote-Jar)")
.titleColor(0xFFFF0000)
@@ -192,10 +193,10 @@ public class AuthManager {
.onClick(() -> {
GuiDisplayer.INSTANCE.displayGui(new GuiPrivacyPolicy());
})
- .build());
+ .build()));
} else {
currentToken = new FailedAuthToken(e);
- NotificationManager.INSTANCE.updateNotification(authenticationFailure, Notification.builder()
+ NotificationManager.getInstance().updateNotification(authenticationFailure, new WidgetNotification(authenticationFailure, Notification.builder()
.title("Auth Error")
.description("Authentication Error Occurred\n"+e.getMessage())
.titleColor(0xFFFF0000)
@@ -203,7 +204,7 @@ public class AuthManager {
.onClick(() -> {
GuiDisplayer.INSTANCE.displayGui(new GuiLoadingError(e));
})
- .build());
+ .build()));
}
logger.error("Accepting the Privacy Policy failed with message {}, trying again in a 2 seconds", String.valueOf(Throwables.getRootCause(e)));
throw new AuthFailedException(e);
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
index 9f55cc7c..27954eca 100644
--- 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
@@ -25,6 +25,7 @@ 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.loader.JarLoader;
import kr.syeyoung.dungeonsguide.launcher.loader.LocalLoader;
import kr.syeyoung.dungeonsguide.launcher.loader.RemoteLoader;
@@ -158,11 +159,13 @@ public class GuiChooseVersion extends SpecialGuiScreen {
null
);
- NotificationManager.INSTANCE.updateNotification(UUID.randomUUID(), Notification.builder()
+ UUID random = UUID.randomUUID();
+ NotificationManager.getInstance().updateNotification(random,
+ new WidgetNotification(random, Notification.builder()
.title("Successfully Copied!")
.description("")
.titleColor(0xFF00FF00)
- .build());
+ .build()));
} else if (button.id == 0) {
dismiss();
Main.getMain().tryReloadingWithSplash(new LocalLoader());
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
index d85909dd..d3622464 100644
--- 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
@@ -20,6 +20,7 @@ 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 net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.Gui;
@@ -69,11 +70,12 @@ public class GuiLoadingError extends SpecialGuiScreen {
null
);
- NotificationManager.INSTANCE.updateNotification(UUID.randomUUID(), Notification.builder()
+ UUID uuid = UUID.randomUUID();
+ NotificationManager.getInstance().updateNotification(uuid, new WidgetNotification(uuid, Notification.builder()
.title("Successfully Copied!")
.description("")
.titleColor(0xFF00FF00)
- .build());
+ .build()));
}
}
diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/tooltip/NotificationManager.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/tooltip/NotificationManager.java
index 6328a831..7e4ccdce 100644
--- a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/tooltip/NotificationManager.java
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/tooltip/NotificationManager.java
@@ -1,6 +1,6 @@
/*
* Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
- * Copyright (C) 2022 cyoung06 (syeyoung)
+ * 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
@@ -18,196 +18,263 @@
package kr.syeyoung.dungeonsguide.launcher.gui.tooltip;
+import kr.syeyoung.dungeonsguide.launcher.guiv2.RootDom;
+import kr.syeyoung.dungeonsguide.launcher.guiv2.elements.GlobalHUDScale;
+import kr.syeyoung.dungeonsguide.launcher.guiv2.primitive.ConstraintBox;
+import kr.syeyoung.dungeonsguide.launcher.guiv2.primitive.Rect;
+import kr.syeyoung.dungeonsguide.launcher.guiv2.primitive.Size;
+import kr.syeyoung.dungeonsguide.launcher.guiv2.renderer.RenderingContext;
+import kr.syeyoung.dungeonsguide.launcher.util.cursor.EnumCursor;
+import kr.syeyoung.dungeonsguide.launcher.util.cursor.GLCursors;
+import lombok.Getter;
import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.FontRenderer;
-import net.minecraft.client.gui.Gui;
import net.minecraft.client.gui.ScaledResolution;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraftforge.client.event.GuiScreenEvent;
import net.minecraftforge.client.event.RenderGameOverlayEvent;
import net.minecraftforge.fml.common.eventhandler.EventPriority;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
+import org.lwjgl.opengl.GL11;
-import java.awt.*;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.UUID;
+import java.io.IOException;
+
+import static org.lwjgl.opengl.GL11.GL_GREATER;
public class NotificationManager {
- public static final NotificationManager INSTANCE = new NotificationManager();
- private NotificationManager() {
+ private final RootDom view;
+ private final Minecraft mc;
+
+ private static final NotificationManager INSTANCE = new NotificationManager();
+ @Getter
+ private final NotificationManagerRootWidget root = new NotificationManagerRootWidget();
- }
- private final Map<UUID, Notification> tooltipList = new HashMap<>();
+ public static NotificationManager getEventHandler() {
+ return INSTANCE;
+ }
- public void updateNotification(UUID uid, Notification tooltip) {
- tooltipList.put(uid, tooltip);
+ public static NotificationManagerRootWidget getInstance() {
+ return getEventHandler().root;
}
- public void removeNotification(UUID uid) {
- tooltipList.remove(uid);
+
+
+ private NotificationManager() {
+ this.mc = Minecraft.getMinecraft();
+
+ view = new RootDom(new GlobalHUDScale(root));
+ guiResize(null);
+ view.setMounted(true);
}
+ @SubscribeEvent()
+ public void guiResize(GuiScreenEvent.InitGuiEvent.Post post){
+ try {
+ view.setRelativeBound(new Rect(0,0, Minecraft.getMinecraft().displayWidth, Minecraft.getMinecraft().displayHeight));
+ view.setAbsBounds(new Rect(0,0, Minecraft.getMinecraft().displayWidth, Minecraft.getMinecraft().displayHeight));
+ view.setSize(new Size(Minecraft.getMinecraft().displayWidth, Minecraft.getMinecraft().displayHeight));
+ view.getLayouter().layout(view, new ConstraintBox(
+ Minecraft.getMinecraft().displayWidth,
+ Minecraft.getMinecraft().displayWidth,
+ Minecraft.getMinecraft().displayHeight,
+ Minecraft.getMinecraft().displayHeight
+ ));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
@SubscribeEvent
- public void onRender(RenderGameOverlayEvent.Post postRender) {
- if (!(postRender.type == RenderGameOverlayEvent.ElementType.EXPERIENCE || postRender.type == RenderGameOverlayEvent.ElementType.JUMPBAR))
- return;
+ public void renderOverlay(RenderGameOverlayEvent.Post postRender) {
+ try {
+ if (!(postRender.type == RenderGameOverlayEvent.ElementType.ALL))
+ return;
+ drawScreen(postRender.partialTicks);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
- ScaledResolution sr = new ScaledResolution(Minecraft.getMinecraft());
- FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
- int widthX = fr.getStringWidth("X");
+ @SubscribeEvent
+ public void renderGui(GuiScreenEvent.DrawScreenEvent.Post postRender) {
+ try {
+ drawScreen(postRender.renderPartialTicks);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
- GlStateManager.pushMatrix();
- GlStateManager.disableDepth();
- GlStateManager.translate(sr.getScaledWidth() - 5, sr.getScaledHeight() -5, 0);
-
- int currY = sr.getScaledHeight() - 5;
-
- for (Notification tooltip : tooltipList.values()) {
- int width, height;
- String[] description = tooltip.getDescription().split("\n");
- width =
- Math.max(
- fr.getStringWidth(tooltip.getTitle()),
- Arrays.stream(description).map(fr::getStringWidth).max(Integer::compareTo).orElse(300)
- ) + 10;
- height = description.length * fr.FONT_HEIGHT + 15 + fr.FONT_HEIGHT;
-
- GlStateManager.translate(0, -height, 0);
- currY -= height;
-
- GlStateManager.pushMatrix();
- GlStateManager.translate(-width, 0, 0);
- Gui.drawRect(0, 0,width,height, 0xFF23272a);
- Gui.drawRect(1, 1, width-1, height-1, 0XFF2c2f33);
-
- if (!tooltip.isUnremovable()) {
- fr.drawString("X", width - widthX - 2, 2, 0xFFFF0000);
- }
- GlStateManager.translate(5,5,0);
- fr.drawString(tooltip.getTitle(), 0,0, tooltip.getTitleColor());
- GlStateManager.translate(0, fr.FONT_HEIGHT + 5, 0);
- int y = 0;
- for (String line : description) {
- fr.drawString(line, 0, y, 0xFFAAAAAA);
- y += fr.FONT_HEIGHT;
- }
- GlStateManager.popMatrix();
+ private void drawScreen( float partialTicks) {
+ int i = Mouse.getEventX();
+ int j = this.mc.displayHeight - Mouse.getEventY();
- tooltip.setBoundRect(new Rectangle(
- sr.getScaledWidth() - width - 5,
- currY,
- width,
- height
+ if (view.isRelayoutRequested()) {
+ view.setRelayoutRequested(false);
+ view.getLayouter().layout(view, new ConstraintBox(
+ Minecraft.getMinecraft().displayWidth,
+ Minecraft.getMinecraft().displayWidth,
+ Minecraft.getMinecraft().displayHeight,
+ Minecraft.getMinecraft().displayHeight
));
+ }
+ ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
+ GlStateManager.pushMatrix();
+ GlStateManager.translate(0,0,50);
+ GlStateManager.disableDepth();
+ GlStateManager.enableBlend();
+ GlStateManager.enableAlpha();
+ GlStateManager.alphaFunc(GL_GREATER, 0);
+ GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, 1, 0);
+ GlStateManager.color(1, 1, 1, 1);
+ GlStateManager.scale(1.0 / scaledResolution.getScaleFactor(), 1.0 / scaledResolution.getScaleFactor(), 1.0d);
+ view.getRenderer().doRender(i, j, i, j, partialTicks, new RenderingContext(), view);
+ GlStateManager.alphaFunc(GL_GREATER, 0.1f);
+ GlStateManager.popMatrix();
+ GlStateManager.enableDepth();
+ GL11.glDisable(GL11.GL_SCISSOR_TEST);
+ }
- currY -= 5;
- GlStateManager.translate(0, -5, 0);
+ private void keyTyped(char typedChar, int keyCode) throws IOException {
+ try {
+ view.keyPressed0(typedChar, keyCode);
+ } catch (Throwable e) {
+ if (e.getMessage() == null || !e.getMessage().contains("hack to stop"))
+ e.printStackTrace();
}
+ }
- GlStateManager.enableDepth();
- GlStateManager.popMatrix();
+ private void keyHeld(int keyCode, char typedChar) throws IOException {
+ try {
+ view.keyHeld0(typedChar, keyCode);
+ } catch (Throwable e) {
+ if (e.getMessage() == null || !e.getMessage().contains("hack to stop"))
+ e.printStackTrace();
+ }
}
- @SubscribeEvent
- public void onGuiPostRender(GuiScreenEvent.DrawScreenEvent.Post rendered) {
- ScaledResolution sr = new ScaledResolution(Minecraft.getMinecraft());
- FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
- int widthX = fr.getStringWidth("X");
- GlStateManager.pushMatrix();
- GlStateManager.disableDepth();
- GlStateManager.translate(sr.getScaledWidth() - 5, sr.getScaledHeight() -5, 0);
-
- int currY = sr.getScaledHeight() - 5;
-
- for (Notification tooltip : tooltipList.values()) {
- int width, height;
- String[] description = tooltip.getDescription().split("\n");
- width =
- Math.max(
- fr.getStringWidth(tooltip.getTitle()),
- Arrays.stream(description).map(fr::getStringWidth).max(Integer::compareTo).orElse(300)
- ) + 10;
- height = description.length * fr.FONT_HEIGHT + 15 + fr.FONT_HEIGHT;
-
- GlStateManager.translate(0, -height, 0);
- currY -= height;
-
- GlStateManager.pushMatrix();
- GlStateManager.translate(-width, 0, 0);
- Gui.drawRect(0, 0,width,height, 0xFF23272a);
- Gui.drawRect(1, 1, width-1, height-1, 0XFF2c2f33);
-
- if (!tooltip.isUnremovable()) {
- if (rendered.mouseX >= sr.getScaledWidth() - 5 - widthX - 2 && rendered.mouseX <= sr.getScaledWidth() - 2
- && rendered.mouseY >= currY + 2 && rendered.mouseY <= currY + 2 + fr.FONT_HEIGHT) {
- fr.drawString("X", width - widthX - 2, 2, 0xFFFFAAAA);
- } else {
- fr.drawString("X", width - widthX - 2, 2, 0xFFFF0000);
- }
- }
+ private void keyReleased(int keyCode, char typedChar) throws IOException {
+ try {
+ view.keyReleased0(typedChar, keyCode);
+ } catch (Throwable e) {
+ if (e.getMessage() == null || !e.getMessage().contains("hack to stop"))
+ e.printStackTrace();
+ }
+ }
- GlStateManager.translate(5,5,0);
- fr.drawString(tooltip.getTitle(), 0,0, tooltip.getTitleColor());
- GlStateManager.translate(0, fr.FONT_HEIGHT + 5, 0);
- int y = 0;
- for (String line : description) {
- fr.drawString(line, 0, y, 0xFFAAAAAA);
- y += fr.FONT_HEIGHT;
- }
- GlStateManager.popMatrix();
+ private boolean mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException {
+ try {
+ return view.mouseClicked0(mouseX, mouseY
+ , mouseX, mouseY, mouseButton);
+ } catch (Throwable e) {
+ if (e.getMessage() == null || !e.getMessage().contains("hack to stop"))
+ e.printStackTrace();
+ }
+ return false;
+ }
- tooltip.setBoundRect(new Rectangle(
- sr.getScaledWidth() - width - 5,
- currY,
- width,
- height
- ));
+ private void mouseReleased(int mouseX, int mouseY, int state) {
+ try {
+ view.mouseReleased0(mouseX, mouseY
+ , mouseX, mouseY, state);
+ } catch (Throwable e) {
+ if (e.getMessage() == null || !e.getMessage().contains("hack to stop"))
+ e.printStackTrace();
+ }
+ }
- currY -= 5;
- GlStateManager.translate(0, -5, 0);
+ private void mouseClickMove(int mouseX, int mouseY, int clickedMouseButton, long timeSinceLastClick) {
+ try {
+ view.mouseClickMove0(mouseX, mouseY
+ , mouseX, mouseY, clickedMouseButton, timeSinceLastClick);
+ } catch (Throwable e) {
+ if (e.getMessage() == null || !e.getMessage().contains("hack to stop"))
+ e.printStackTrace();
}
+ }
- GlStateManager.enableDepth();
- GlStateManager.popMatrix();
+ private void mouseMove(int mouseX, int mouseY) {
+ try {
+ view.mouseMoved0(mouseX, mouseY
+ , mouseX, mouseY, true);
+ } catch (Throwable e) {
+ if (e.getMessage() == null || !e.getMessage().contains("hack to stop"))
+ e.printStackTrace();
+ }
}
+ private int touchValue;
+ private int eventButton;
+ private long lastMouseEvent;
+
+
+ private int lastX, lastY;
+
+
@SubscribeEvent(priority = EventPriority.HIGHEST)
- public void onMouseInput(GuiScreenEvent.MouseInputEvent.Pre mouseInputEvent) {
- ScaledResolution sr = new ScaledResolution(Minecraft.getMinecraft());
- FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
- int mouseX = Mouse.getX() / sr.getScaleFactor();
- int mouseY = (Minecraft.getMinecraft().displayHeight - Mouse.getY() +3)/ sr.getScaleFactor();
- for (Map.Entry<UUID, Notification> tooltip_ : tooltipList.entrySet()) {
- Notification tooltip = tooltip_.getValue();
- if (tooltip.getBoundRect() == null) continue;;
- if (tooltip.getBoundRect().contains(mouseX, mouseY)) {
-
- mouseInputEvent.setCanceled(true);
-
- if (Mouse.getEventButton() == -1) return;
- if (!Mouse.getEventButtonState()) return;
-
- int dx = mouseX - tooltip.getBoundRect().x;
- int dy = mouseY - tooltip.getBoundRect().y;
-
- if (!tooltip.isUnremovable()) {
- tooltipList.remove(tooltip_.getKey());
+ public void handleMouseInput(GuiScreenEvent.MouseInputEvent.Pre mouseInputEvent) throws IOException {
+ try {
+ int i = Mouse.getEventX();
+ int j = this.mc.displayHeight - Mouse.getEventY();
+ int k = Mouse.getEventButton();
+
+ if (Mouse.getEventButtonState()) {
+ if (this.mc.gameSettings.touchscreen && this.touchValue++ > 0) {
+ return;
}
- if (dx >= tooltip.getBoundRect().width - 2 - fr.getStringWidth("X") && dx <= tooltip.getBoundRect().width - 2
- && dy >= 2 && dy <= 2 + fr.FONT_HEIGHT) {
- } else {
- if (tooltip.getOnClick() != null) tooltip.getOnClick().run();
+
+ this.eventButton = k;
+ this.lastMouseEvent = Minecraft.getSystemTime();
+ if (this.mouseClicked(i, j, this.eventButton))
+ mouseInputEvent.setCanceled(true);
+ } else if (k != -1) {
+ if (this.mc.gameSettings.touchscreen && --this.touchValue > 0) {
+ return;
}
- return;
+ this.eventButton = -1;
+ this.mouseReleased(i, j, k);
+ } else if (this.eventButton != -1 && this.lastMouseEvent > 0L) {
+ long l = Minecraft.getSystemTime() - this.lastMouseEvent;
+ this.mouseClickMove(i, j, this.eventButton, l);
}
+ if (lastX != i || lastY != j) {
+ try {
+ EnumCursor prevCursor = view.getCurrentCursor();
+ view.setCursor(EnumCursor.DEFAULT);
+ this.mouseMove(i, j);
+ EnumCursor newCursor = view.getCurrentCursor();
+ if (prevCursor != newCursor) Mouse.setNativeCursor(GLCursors.getCursor(newCursor));
+ } catch (Throwable e) {
+ if (e.getMessage() == null || !e.getMessage().contains("hack to stop"))
+ e.printStackTrace();
+ }
+ }
+
+
+ int wheel = Mouse.getEventDWheel();
+ if (wheel != 0) {
+ boolean cancel = view.mouseScrolled0(i, j, i, j, wheel);
+ if (cancel) mouseInputEvent.setCanceled(true);
+ }
+ lastX = i;
+ lastY = j;
+ } catch (Throwable e) {
+ e.printStackTrace();
}
}
+ @SubscribeEvent(priority = EventPriority.HIGHEST)
+ public void handleKeyboardInput(GuiScreenEvent.KeyboardInputEvent.Pre keyboardInputEvent) throws IOException {
+ if (Keyboard.getEventKeyState()) {
+ if (Keyboard.isRepeatEvent())
+ this.keyHeld(Keyboard.getEventKey(), Keyboard.getEventCharacter());
+ else
+ this.keyTyped(Keyboard.getEventCharacter(), Keyboard.getEventKey());
+ } else {
+ this.keyReleased(Keyboard.getEventKey(), Keyboard.getEventCharacter());
+ }
+ }
}
diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/tooltip/NotificationManagerRootWidget.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/tooltip/NotificationManagerRootWidget.java
new file mode 100644
index 00000000..6cbe78c6
--- /dev/null
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/tooltip/NotificationManagerRootWidget.java
@@ -0,0 +1,56 @@
+/*
+ * 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.tooltip;
+
+import kr.syeyoung.dungeonsguide.launcher.guiv2.BindableAttribute;
+import kr.syeyoung.dungeonsguide.launcher.guiv2.Widget;
+import kr.syeyoung.dungeonsguide.launcher.guiv2.DomElement;
+import kr.syeyoung.dungeonsguide.launcher.guiv2.Widget;
+import kr.syeyoung.dungeonsguide.launcher.guiv2.elements.Column;
+import kr.syeyoung.dungeonsguide.launcher.guiv2.layouter.Layouter;
+import kr.syeyoung.dungeonsguide.launcher.guiv2.primitive.ConstraintBox;
+import kr.syeyoung.dungeonsguide.launcher.guiv2.primitive.Size;
+import kr.syeyoung.dungeonsguide.launcher.guiv2.renderer.OnlyChildrenRenderer;
+import kr.syeyoung.dungeonsguide.launcher.guiv2.renderer.Renderer;
+import kr.syeyoung.dungeonsguide.launcher.guiv2.xml.AnnotatedImportOnlyWidget;
+import kr.syeyoung.dungeonsguide.launcher.guiv2.xml.annotations.Bind;
+import net.minecraft.util.ResourceLocation;
+
+import java.util.*;
+
+public class NotificationManagerRootWidget extends AnnotatedImportOnlyWidget {
+ @Bind(variableName = "listApi")
+ public final BindableAttribute<Column> api = new BindableAttribute<>(Column.class);
+
+ public NotificationManagerRootWidget() {
+ super(new ResourceLocation("dungeons_guide_loader:gui/tooltips/tooltipHolder.gui"));
+ }
+
+ private final Map<UUID, Widget> tooltipList = new HashMap<>();
+
+ public void updateNotification(UUID uid, Widget tooltip) {
+ Widget old = tooltipList.put(uid, tooltip);
+ if (old != null) api.getValue().removeWidget(old);
+ api.getValue().addWidget(tooltip);
+ }
+ public void removeNotification(UUID uid) {
+ Widget old = tooltipList.remove(uid);
+ if (old != null) api.getValue().removeWidget(old);
+ }
+}
diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/tooltip/WidgetNotification.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/tooltip/WidgetNotification.java
new file mode 100644
index 00000000..8683b4fd
--- /dev/null
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/tooltip/WidgetNotification.java
@@ -0,0 +1,64 @@
+/*
+ * 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.tooltip;
+
+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.util.ResourceLocation;
+
+import java.util.UUID;
+
+public class WidgetNotification extends AnnotatedImportOnlyWidget {
+ private Notification notification;
+
+
+ @Bind(variableName = "title")
+ public final BindableAttribute<String> title = new BindableAttribute<>(String.class);
+ @Bind(variableName = "description")
+ public final BindableAttribute<String> description = new BindableAttribute<>(String.class);
+ @Bind(variableName = "color")
+ public final BindableAttribute<Integer> color = new BindableAttribute<>(Integer.class);
+ @Bind(variableName = "closeVisibility")
+ public final BindableAttribute<String> closeVisibility = new BindableAttribute<>(String.class);
+
+ private UUID uuid;
+ public WidgetNotification(UUID uuid, Notification notification) {
+ super(new ResourceLocation("dungeons_guide_loader:gui/tooltips/tooltip.gui"));
+ this.notification =notification;
+ title.setValue(notification.getTitle());
+ color.setValue(notification.getTitleColor());
+ description.setValue(notification.getDescription());
+ closeVisibility.setValue(notification.isUnremovable() ? "hide" : "show");
+ this.uuid = uuid;
+ }
+
+ @On(functionName = "close")
+ public void close() {
+ if (!notification.isUnremovable())
+ NotificationManager.getInstance().removeNotification(uuid);
+ }
+
+ @Override
+ public boolean mouseClicked(int absMouseX, int absMouseY, double relMouseX, double relMouseY, int mouseButton) {
+ if (notification.getOnClick() != null) notification.getOnClick().run();
+ return true;
+ }
+}
diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/tooltip/WidgetNotificationAutoClose.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/tooltip/WidgetNotificationAutoClose.java
new file mode 100644
index 00000000..90e2359b
--- /dev/null
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/tooltip/WidgetNotificationAutoClose.java
@@ -0,0 +1,86 @@
+/*
+ * 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.tooltip;
+
+import kr.syeyoung.dungeonsguide.launcher.guiv2.BindableAttribute;
+import kr.syeyoung.dungeonsguide.launcher.guiv2.DomElement;
+import kr.syeyoung.dungeonsguide.launcher.guiv2.primitive.Size;
+import kr.syeyoung.dungeonsguide.launcher.guiv2.renderer.Renderer;
+import kr.syeyoung.dungeonsguide.launcher.guiv2.renderer.RenderingContext;
+import kr.syeyoung.dungeonsguide.launcher.guiv2.renderer.SingleChildRenderer;
+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.util.ResourceLocation;
+
+import java.util.UUID;
+
+public class WidgetNotificationAutoClose extends AnnotatedImportOnlyWidget implements Renderer {
+ private Notification notification;
+
+
+ @Bind(variableName = "title")
+ public final BindableAttribute<String> title = new BindableAttribute<>(String.class);
+ @Bind(variableName = "description")
+ public final BindableAttribute<String> description = new BindableAttribute<>(String.class);
+ @Bind(variableName = "color")
+ public final BindableAttribute<Integer> color = new BindableAttribute<>(Integer.class);
+ @Bind(variableName = "closeVisibility")
+ public final BindableAttribute<String> closeVisibility = new BindableAttribute<>(String.class);
+ @Bind(variableName = "size")
+ public final BindableAttribute<Size> size = new BindableAttribute<>(Size.class);
+ @Bind(variableName = "width")
+ public final BindableAttribute<Double> width = new BindableAttribute<>(Double.class);
+
+ private UUID uuid;
+ private long delay;
+ private long now = -1;
+ public WidgetNotificationAutoClose(UUID uuid, Notification notification, long delay) {
+ super(new ResourceLocation("dungeons_guide_loader:gui/tooltips/tooltipClosing.gui"));
+ this.notification =notification;
+ title.setValue(notification.getTitle());
+ color.setValue(notification.getTitleColor());
+ description.setValue(notification.getDescription());
+ closeVisibility.setValue(notification.isUnremovable() ? "hide" : "show");
+ this.uuid = uuid;
+ this.delay = delay;
+
+ }
+
+ @On(functionName = "close")
+ public void close() {
+ if (!notification.isUnremovable())
+ NotificationManager.getInstance().removeNotification(uuid);
+ }
+
+ @Override
+ public boolean mouseClicked(int absMouseX, int absMouseY, double relMouseX, double relMouseY, int mouseButton) {
+ if (notification.getOnClick() != null) notification.getOnClick().run();
+ return true;
+ }
+
+ @Override
+ public void doRender(int absMouseX, int absMouseY, double relMouseX, double relMouseY, float partialTicks, RenderingContext context, DomElement buildContext) {
+ if (now == -1) now = System.currentTimeMillis();
+ width.setValue((System.currentTimeMillis() - now)* size.getValue().getWidth() /delay );
+ if (System.currentTimeMillis() - now > delay)
+ NotificationManager.getInstance().removeNotification(uuid);
+ SingleChildRenderer.INSTANCE.doRender(absMouseX, absMouseY, relMouseX, relMouseY, partialTicks, context, buildContext);
+ }
+}
diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/Text.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/Text.java
index 761c7a0d..14bb30e3 100644
--- a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/Text.java
+++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/Text.java
@@ -100,6 +100,7 @@ public class Text extends AnnotatedExportOnlyWidget {
textStyle.textShader = new SingleColorShader(color.getValue());
textStyle.underlineShader = new SingleColorShader(color.getValue());
textStyle.strikeThroughShader = new SingleColorShader(color.getValue());
+ textStyle.backgroundShader = null;
textStyle.topAscent = lineSpacing.getValue() - 1;
textStyle.size = size.getValue();
TextSpan textSpan = new TextSpan(textStyle, "");
diff --git a/loader/src/main/resources/assets/dungeons_guide_loader/gui/fi b/loader/src/main/resources/assets/dungeons_guide_loader/gui/fi
deleted file mode 100644
index e69de29b..00000000
--- a/loader/src/main/resources/assets/dungeons_guide_loader/gui/fi
+++ /dev/null
diff --git a/loader/src/main/resources/assets/dungeons_guide_loader/gui/tooltips/tooltip.gui b/loader/src/main/resources/assets/dungeons_guide_loader/gui/tooltips/tooltip.gui
new file mode 100644
index 00000000..00ac2caf
--- /dev/null
+++ b/loader/src/main/resources/assets/dungeons_guide_loader/gui/tooltips/tooltip.gui
@@ -0,0 +1,48 @@
+<!--
+ ~ 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/>.
+ -->
+
+<UnconstrainedBox>
+ <size width="200">
+ <padding top="2.5" bottom="2.5" right="5" left="5">
+ <bgcolor backgroundColor="#FFFFFFFF">
+ <padding left="1" right="1" top="1" bottom="1">
+ <bgcolor backgroundColor="#FF111111">
+ <padding left="5" right="5" top="5" bottom="5">
+ <col crossAlign="START">
+ <row crossAlign="END">
+ <Text bind:text="title" bind:color="color" size="8"/>
+ <SelectiveContainer bind:visible="closeVisibility">
+ <row slot="show">
+ <size height="0" width="5"/>
+ <size height="10" width="10">
+ <RoundButton text="X" on:click="close"/>
+ </size>
+ </row>
+ <size width="0" height="0" slot="hide"/>
+ </SelectiveContainer>
+ </row>
+ <size width="0" height="3"/>
+ <Text bind:text="description" color="#FFAAAAAA"/>
+ </col>
+ </padding>
+ </bgcolor>
+ </padding>
+ </bgcolor>
+ </padding>
+ </size>
+</UnconstrainedBox> \ No newline at end of file
diff --git a/loader/src/main/resources/assets/dungeons_guide_loader/gui/tooltips/tooltipClosing.gui b/loader/src/main/resources/assets/dungeons_guide_loader/gui/tooltips/tooltipClosing.gui
new file mode 100644
index 00000000..d28ff990
--- /dev/null
+++ b/loader/src/main/resources/assets/dungeons_guide_loader/gui/tooltips/tooltipClosing.gui
@@ -0,0 +1,63 @@
+<!--
+ ~ 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/>.
+ -->
+
+<UnconstrainedBox>
+ <size width="200">
+ <padding top="2.5" bottom="2.5" right="5" left="5">
+ <bgcolor backgroundColor="#FFFFFFFF">
+ <padding left="1" right="1" top="1" bottom="1">
+ <bgcolor backgroundColor="#FF111111">
+ <col crossAlign="STRETCH">
+ <padding left="5" right="5" top="5" bottom="5">
+ <col crossAlign="START">
+ <row crossAlign="END">
+ <flexible>
+ <Text bind:text="title" bind:color="color" size="8"/>
+ </flexible>
+ <SelectiveContainer bind:visible="closeVisibility">
+ <row slot="show">
+ <size height="0" width="5"/>
+ <size height="10" width="10">
+ <RoundButton text="X" on:click="close"/>
+ </size>
+ </row>
+ <size width="0" height="0" slot="hide"/>
+ </SelectiveContainer>
+ </row>
+ <size width="0" height="3"/>
+ <Text bind:text="description" color="#FFAAAAAA"/>
+ </col>
+ </padding>
+ <measure bind:size="size">
+ <size height="3">
+ <bgcolor backgroundColor="#FFFFFFFF">
+ <align hAlign="START" vAlign="CENTER">
+ <size bind:width="width">
+ <bgcolor backgroundColor="#FF1E4684"/>
+ </size>
+ </align>
+ </bgcolor>
+ </size>
+ </measure>
+ </col>
+ </bgcolor>
+ </padding>
+ </bgcolor>
+ </padding>
+ </size>
+</UnconstrainedBox> \ No newline at end of file
diff --git a/loader/src/main/resources/assets/dungeons_guide_loader/gui/tooltips/tooltipHolder.gui b/loader/src/main/resources/assets/dungeons_guide_loader/gui/tooltips/tooltipHolder.gui
new file mode 100644
index 00000000..5d4eaf97
--- /dev/null
+++ b/loader/src/main/resources/assets/dungeons_guide_loader/gui/tooltips/tooltipHolder.gui
@@ -0,0 +1,6 @@
+<align hAlign="END" vAlign="END">
+ <padding bottom="2.5">
+ <col mainAlign="END" crossAlign="END" bind:api="listApi">
+ </col>
+ </padding>
+</align>