diff options
author | syeyoung <cyoung06@naver.com> | 2023-02-07 10:23:39 +0900 |
---|---|---|
committer | syeyoung <cyoung06@naver.com> | 2023-02-07 10:23:39 +0900 |
commit | b9f5d57e6ceb50067ac88863655ebfdb92985f7a (patch) | |
tree | a4b054872b88d98aadc1949e4b44709d832929a6 /loader/src/main/java/kr | |
parent | 544fdb38a545ff346a8d12349067c805caac3862 (diff) | |
download | Skyblock-Dungeons-Guide-b9f5d57e6ceb50067ac88863655ebfdb92985f7a.tar.gz Skyblock-Dungeons-Guide-b9f5d57e6ceb50067ac88863655ebfdb92985f7a.tar.bz2 Skyblock-Dungeons-Guide-b9f5d57e6ceb50067ac88863655ebfdb92985f7a.zip |
- New Privacy Policy GUI
Signed-off-by: syeyoung <cyoung06@naver.com>
Diffstat (limited to 'loader/src/main/java/kr')
9 files changed, 192 insertions, 102 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 4a7ef695..6039823b 100755 --- a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/Main.java +++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/Main.java @@ -32,6 +32,7 @@ import kr.syeyoung.dungeonsguide.launcher.gui.tooltip.WidgetNotificationAutoClos import kr.syeyoung.dungeonsguide.launcher.guiv2.elements.richtext.fonts.DefaultFontRenderer; import kr.syeyoung.dungeonsguide.launcher.loader.*; import kr.syeyoung.dungeonsguide.launcher.util.ProgressStateHolder; +import kr.syeyoung.dungeonsguide.launcher.util.cursor.GLCursors; import lombok.Getter; import net.minecraft.client.Minecraft; import net.minecraft.client.resources.IReloadableResourceManager; @@ -61,6 +62,7 @@ public class Main { public static final String MOD_ID = "dungeons_guide_loader"; public static final String VERSION = "4.0.0"; + public static final String POLICY = "https://v2.dungeons.guide/privacyPolicy.gui"; public static final String DOMAIN = "https://v2.dungeons.guide/api"; private static Main main; @@ -278,6 +280,10 @@ public class Main @EventHandler public void preInit(FMLPreInitializationEvent preInitializationEvent) { + try { + GLCursors.setupCursors(); + } catch (Exception e) {} + Security.addProvider(new BouncyCastleProvider()); // setup static variables main = this; 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 9a491b08..6f9a2d65 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 @@ -27,10 +27,12 @@ import kr.syeyoung.dungeonsguide.launcher.exceptions.auth.AuthenticationUnavaila 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.GuiPrivacyPolicy; +import kr.syeyoung.dungeonsguide.launcher.gui.screen.WidgetPrivacyPolicy; 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.guiv2.GuiScreenAdapter; +import kr.syeyoung.dungeonsguide.launcher.guiv2.elements.GlobalHUDScale; import net.minecraft.client.Minecraft; import net.minecraftforge.common.MinecraftForge; import org.apache.logging.log4j.LogManager; @@ -73,6 +75,7 @@ public class AuthManager { else if (currentToken instanceof PrivacyPolicyRequiredToken) throw new PrivacyPolicyRequiredException(); throw new IllegalStateException("weird token: "+currentToken); } + final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1, new ThreadFactoryBuilder().setNameFormat("DgAuth Pool").build()); private volatile boolean initlock = false; @@ -85,8 +88,6 @@ public class AuthManager { initlock = true; - ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("DgAuth Pool").build(); - final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1, namedThreadFactory); scheduler.scheduleAtFixedRate(() -> { boolean shouldReAuth = false; if (getToken().isUserVerified() && !getToken().getUUID().replace("-", "").equals(Minecraft.getMinecraft().getSession().getPlayerID())) { @@ -131,7 +132,7 @@ public class AuthManager { if (currentToken instanceof PrivacyPolicyRequiredToken) { - GuiDisplayer.INSTANCE.displayGui(new GuiPrivacyPolicy()); + GuiDisplayer.INSTANCE.displayGui(new GuiScreenAdapter(new GlobalHUDScale(new WidgetPrivacyPolicy()))); throw new PrivacyPolicyRequiredException(); } @@ -140,12 +141,13 @@ public class AuthManager { NotificationManager.getInstance().removeNotification(privacyPolicyRequired); } catch (Exception e) { if (e instanceof PrivacyPolicyRequiredException) { + NotificationManager.getInstance().removeNotification(authenticationFailure); 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) .onClick(() -> { - GuiDisplayer.INSTANCE.displayGui(new GuiPrivacyPolicy()); + GuiDisplayer.INSTANCE.displayGui(new GuiScreenAdapter(new GlobalHUDScale(new WidgetPrivacyPolicy()))); }) .build())); } else { @@ -167,8 +169,18 @@ public class AuthManager { return currentToken; } + private volatile boolean accepting = false; + public synchronized void acceptPrivacyPolicy(long version) { + if (accepting) return; + accepting = true; + scheduler.schedule(() -> {try { + acceptPrivacyPolicy0(version); + } catch (Exception e) {e.printStackTrace();} finally { + accepting = false; + }}, 0, TimeUnit.MILLISECONDS); + } - public AuthToken acceptPrivacyPolicy(long version) { + private AuthToken acceptPrivacyPolicy0(long version) { if (reauthLock) { while(reauthLock); return currentToken; @@ -188,7 +200,7 @@ public class AuthManager { .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) .onClick(() -> { - GuiDisplayer.INSTANCE.displayGui(new GuiPrivacyPolicy()); + GuiDisplayer.INSTANCE.displayGui(new GuiScreenAdapter(new GlobalHUDScale(new WidgetPrivacyPolicy()))); }) .build())); } else { 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 index 35d9a9ea..ad942ffb 100644 --- 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 @@ -20,6 +20,7 @@ package kr.syeyoung.dungeonsguide.launcher.gui.screen; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiMainMenu; +import net.minecraft.client.gui.GuiScreen; import net.minecraftforge.client.event.GuiOpenEvent; import net.minecraftforge.fml.common.eventhandler.EventPriority; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; @@ -31,7 +32,7 @@ public class GuiDisplayer { public static GuiDisplayer INSTANCE = new GuiDisplayer(); private GuiDisplayer() {} - private Queue<SpecialGuiScreen> guiScreensToShow = new LinkedList<>(); + private Queue<GuiScreen> guiScreensToShow = new LinkedList<>(); private boolean isMcLoaded; @@ -40,23 +41,21 @@ public class GuiDisplayer { if (guiOpenEvent.gui instanceof GuiMainMenu) { isMcLoaded = true; } - if (guiScreensToShow.size() > 0 && guiOpenEvent.gui != guiScreensToShow.peek()) { - SpecialGuiScreen gui = guiScreensToShow.peek(); + if (isMcLoaded && !guiScreensToShow.isEmpty()) { + GuiScreen gui = guiScreensToShow.poll(); if (gui == null) return; - gui.setOnDismiss(guiScreensToShow::poll); guiOpenEvent.gui = gui; } } - public void displayGui(SpecialGuiScreen specialGuiScreen) { + public void displayGui(GuiScreen 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); + if (isMcLoaded && Minecraft.getMinecraft().isCallingFromMinecraftThread()) { + Minecraft.getMinecraft().displayGuiScreen(null); + } else if (isMcLoaded) { + Minecraft.getMinecraft().addScheduledTask(() -> Minecraft.getMinecraft().displayGuiScreen(null)); } } } diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/screen/GuiPrivacyPolicy.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/screen/GuiPrivacyPolicy.java deleted file mode 100644 index 66b26111..00000000 --- a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/screen/GuiPrivacyPolicy.java +++ /dev/null @@ -1,83 +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.auth.AuthManager; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.FontRenderer; -import net.minecraft.client.gui.GuiButton; -import net.minecraft.client.gui.ScaledResolution; -import org.lwjgl.opengl.GL11; - -import java.io.IOException; - -public class GuiPrivacyPolicy extends SpecialGuiScreen { - @Override - public void initGui() { - super.initGui(); - ScaledResolution sr = new ScaledResolution(Minecraft.getMinecraft()); - - int width = Math.min(300, sr.getScaledWidth() / 2 - 20); - - this.buttonList.add(new GuiButton(0, sr.getScaledWidth()/2 + 10,sr.getScaledHeight()-40, width, 20,"Accept Privacy Policy")); - this.buttonList.add(new GuiButton(1, sr.getScaledWidth() / 2 - 10 - width,sr.getScaledHeight()-40, width, 20,"Deny and Play Without DG")); - } - - - @Override - protected void actionPerformed(GuiButton button) throws IOException { - super.actionPerformed(button); - if (button.id == 0) { - // accept - try { - AuthManager.getInstance().acceptPrivacyPolicy(1); - } catch (Exception e) { - e.printStackTrace(); -// GuiDisplayer.INSTANCE.displayGui(new GuiLoadingError(e)); - // display tooltip. - } - dismiss(); - } else if (button.id == 1) { - dismiss(); - } - } - - - @Override - public void drawScreen(int mouseX, int mouseY, float partialTicks) { - super.drawBackground(0); - - ScaledResolution sr = new ScaledResolution(Minecraft.getMinecraft()); - FontRenderer fontRenderer = Minecraft.getMinecraft().fontRendererObj; - - final String ACCEPT_POLICY_MSG = "Please accept or deny the Dungeons Guide Privacy Policy to continue"; - - fontRenderer.drawString(ACCEPT_POLICY_MSG, (sr.getScaledWidth()-fontRenderer.getStringWidth(ACCEPT_POLICY_MSG))/2,40,0xFFFF0000); - fontRenderer.drawString("Blah blah legal stuff", (sr.getScaledWidth()-fontRenderer.getStringWidth(ACCEPT_POLICY_MSG))/2,sr.getScaledHeight() / 2, 0xFFFFFFFF); - - 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 index efe5c36a..280b5b3e 100644 --- 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 @@ -29,7 +29,8 @@ public abstract class SpecialGuiScreen extends GuiScreen { } protected void dismiss() { - onDismiss.run(); + if (onDismiss != null) + onDismiss.run(); Minecraft.getMinecraft().displayGuiScreen(null); } } diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/screen/WidgetPrivacyPolicy.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/screen/WidgetPrivacyPolicy.java new file mode 100644 index 00000000..0ee99c92 --- /dev/null +++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/gui/screen/WidgetPrivacyPolicy.java @@ -0,0 +1,101 @@ +/* + * 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.LetsEncrypt; +import kr.syeyoung.dungeonsguide.launcher.Main; +import kr.syeyoung.dungeonsguide.launcher.auth.AuthManager; +import kr.syeyoung.dungeonsguide.launcher.guiv2.BindableAttribute; +import kr.syeyoung.dungeonsguide.launcher.guiv2.Widget; +import kr.syeyoung.dungeonsguide.launcher.guiv2.xml.AnnotatedImportOnlyWidget; +import kr.syeyoung.dungeonsguide.launcher.guiv2.xml.DomElementRegistry; +import kr.syeyoung.dungeonsguide.launcher.guiv2.xml.ParsedWidgetConverter; +import kr.syeyoung.dungeonsguide.launcher.guiv2.xml.annotations.Bind; +import kr.syeyoung.dungeonsguide.launcher.guiv2.xml.annotations.On; +import kr.syeyoung.dungeonsguide.launcher.guiv2.xml.data.Parser; +import kr.syeyoung.dungeonsguide.launcher.guiv2.xml.data.ParserElement; +import kr.syeyoung.dungeonsguide.launcher.guiv2.xml.data.W3CBackedParser; +import net.minecraft.client.Minecraft; +import net.minecraft.client.audio.PositionedSoundRecord; +import net.minecraft.util.ResourceLocation; +import org.apache.commons.io.IOUtils; + +import javax.net.ssl.HttpsURLConnection; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.Collections; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class WidgetPrivacyPolicy extends AnnotatedImportOnlyWidget { + private static final ExecutorService executor = Executors.newSingleThreadExecutor(); + @Bind(variableName = "policy") + public final BindableAttribute<Widget> policy = new BindableAttribute<>(Widget.class); + @Bind(variableName = "policyVisibility") + public final BindableAttribute<String> policyVisibility = new BindableAttribute<>(String.class, "loading"); + + @Bind(variableName = "policyVersion") + public final BindableAttribute<Integer> version = new BindableAttribute<>(Integer.class, 0); + + public WidgetPrivacyPolicy() { + super(new ResourceLocation("dungeons_guide_loader:gui/privacyPolicy/privacyPolicy.gui")); + reload(); + } + + @On(functionName = "accept") + public void accept() { + Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F)); + AuthManager.getInstance().acceptPrivacyPolicy(version.getValue()); + Minecraft.getMinecraft().displayGuiScreen(null); + } + @On(functionName = "deny") + public void deny() { + Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F)); + Minecraft.getMinecraft().displayGuiScreen(null); + } + + @On(functionName = "reload") + public void reload() { + Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F)); + policyVisibility.setValue("loading"); + executor.submit(() -> { + try { + HttpsURLConnection urlConnection = (HttpsURLConnection) new URL(Main.POLICY).openConnection(); + urlConnection.setSSLSocketFactory(LetsEncrypt.LETS_ENCRYPT); + urlConnection.setRequestProperty("User-Agent", "DungeonsGuide/4.0"); + urlConnection.setConnectTimeout(1000); + urlConnection.setReadTimeout(3000); + urlConnection.setRequestMethod("GET"); + urlConnection.setDoInput(true); + + try (W3CBackedParser parser = new W3CBackedParser(urlConnection.getInputStream())) { + ParserElement element = parser.getRootNode(); + ParsedWidgetConverter converter = DomElementRegistry.obtainConverter(element.getNodeName()); + Widget w = converter.convert(this, element); + policy.setValue(w); + policyVisibility.setValue("loaded"); + } + } catch (Exception e) { + e.printStackTrace(); + policyVisibility.setValue("failed"); + } + }); + } +} diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/GuiScreenAdapter.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/GuiScreenAdapter.java index d4d46834..44dfb230 100644 --- a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/GuiScreenAdapter.java +++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/GuiScreenAdapter.java @@ -261,7 +261,8 @@ public class GuiScreenAdapter extends GuiScreen { view.setCursor(EnumCursor.DEFAULT); this.mouseMove(i, j); EnumCursor newCursor = view.getCurrentCursor(); - if (prevCursor != newCursor) Mouse.setNativeCursor(GLCursors.getCursor(newCursor)); + if (prevCursor != newCursor) + Mouse.setNativeCursor(GLCursors.getCursor(newCursor)); } catch (Throwable e) { if (e.getMessage() == null || !e.getMessage().contains("hack to stop")) e.printStackTrace(); diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/PolicyVersion.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/PolicyVersion.java new file mode 100644 index 00000000..e0384810 --- /dev/null +++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/elements/PolicyVersion.java @@ -0,0 +1,52 @@ +/* + * 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.guiv2.elements; + +import kr.syeyoung.dungeonsguide.launcher.guiv2.BindableAttribute; +import kr.syeyoung.dungeonsguide.launcher.guiv2.DomElement; +import kr.syeyoung.dungeonsguide.launcher.guiv2.Widget; +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.xml.AnnotatedExportOnlyWidget; +import kr.syeyoung.dungeonsguide.launcher.guiv2.xml.annotations.Export; + +import java.util.Collections; +import java.util.List; + +public class PolicyVersion extends AnnotatedExportOnlyWidget implements Layouter { + @Export(attributeName = "version") + public final BindableAttribute<Integer> docVersion = new BindableAttribute<>(Integer.class); + @Export(attributeName = "policyVersion") + public final BindableAttribute<Integer> bindVersion = new BindableAttribute<>(Integer.class); + + public PolicyVersion() { + docVersion.exportTo(bindVersion); + } + + @Override + public List<Widget> build(DomElement buildContext) { + return Collections.EMPTY_LIST; + } + + @Override + public Size layout(DomElement buildContext, ConstraintBox constraintBox) { + return new Size(0,0); + } +} diff --git a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/xml/DomElementRegistry.java b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/xml/DomElementRegistry.java index 4a4eff58..efa7a5fc 100644 --- a/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/xml/DomElementRegistry.java +++ b/loader/src/main/java/kr/syeyoung/dungeonsguide/launcher/guiv2/xml/DomElementRegistry.java @@ -84,6 +84,7 @@ public class DomElementRegistry { register("InvertStencil", new ExportedWidgetConverter(NegativeStencil::new)); register("WrapGrid", new ExportedWidgetConverter(Wrap::new)); + register("PolicyVersion", new ExportedWidgetConverter(PolicyVersion::new)); register("ColorButton", new DelegatingWidgetConverter(new ResourceLocation("dungeons_guide_loader:gui/elements/simpleButton.gui"))); register("RoundButton", new DelegatingWidgetConverter(new ResourceLocation("dungeons_guide_loader:gui/elements/dgButton.gui"))); register("IconButton", new DelegatingWidgetConverter(new ResourceLocation("dungeons_guide_loader:gui/elements/iconButton.gui"))); |