From f3410c50bdcc5c5ddbbdfa05ad539d178dfdbf84 Mon Sep 17 00:00:00 2001
From: syeyoung <cyoung06@naver.com>
Date: Sat, 4 Feb 2023 02:03:37 +0900
Subject: - Configuration Overhaul - Move to new system - more shaders!!

Signed-off-by: syeyoung <cyoung06@naver.com>
---
 .../dungeonsguide/mod/commands/CommandDgDebug.java |  98 ++++---
 .../mod/commands/CommandDungeonsGuide.java         |   6 +-
 .../mod/config/guiconfig/ConfigPanelCreator.java   |  40 ---
 .../mod/config/guiconfig/GuiConfigV2.java          |  59 ----
 .../mod/config/guiconfig/MCategory.java            | 103 -------
 .../mod/config/guiconfig/MCategoryElement.java     |  82 ------
 .../mod/config/guiconfig/MFeature.java             | 153 ----------
 .../mod/config/guiconfig/MFeatureEdit.java         | 114 --------
 .../mod/config/guiconfig/MNotFound.java            |  38 ---
 .../mod/config/guiconfig/MPanelCategory.java       |  83 ------
 .../mod/config/guiconfig/MParameterEdit.java       | 220 ---------------
 .../mod/config/guiconfig/NestedCategory.java       |  54 ----
 .../mod/config/guiconfig/RootConfigPanel.java      | 313 ---------------------
 .../mod/config/guiconfig/configv3/FeatureItem.java |   2 +
 .../config/guiconfig/configv3/MainPageWidget.java  |   5 +
 .../config/guiconfig/configv3/ParameterItem.java   |  72 +++++
 .../dungeonsguide/mod/config/types/AColor.java     |   2 +
 .../mod/config/types/FeatureTypeHandler.java       |  32 +++
 .../dungeonsguide/mod/config/types/TCAColor.java   | 109 ++++++-
 .../dungeonsguide/mod/config/types/TCBoolean.java  |  36 ++-
 .../dungeonsguide/mod/config/types/TCColor.java    |  41 ---
 .../dungeonsguide/mod/config/types/TCEnum.java     | 104 +++++++
 .../dungeonsguide/mod/config/types/TCFloat.java    |  59 +++-
 .../mod/config/types/TCGUIPosition.java            |   7 +-
 .../dungeonsguide/mod/config/types/TCInteger.java  |  55 +++-
 .../dungeonsguide/mod/config/types/TCKeybind.java  |  64 ++++-
 .../mod/config/types/TCRectangle.java              |   7 +-
 .../dungeonsguide/mod/config/types/TCString.java   |  31 +-
 .../mod/config/types/TCStringList.java             |   7 +-
 .../mod/config/types/TCTextStyle.java              |  15 +-
 .../mod/config/types/TCTextStyleList.java          |  11 +-
 .../mod/config/types/TypeConverter.java            |  29 --
 .../mod/config/types/TypeConverterRegistry.java    |  32 +--
 .../mod/config/types/coloredit/AlphaBar.java       | 138 +++++++++
 .../mod/config/types/coloredit/ChromaBar.java      | 149 ++++++++++
 .../mod/config/types/coloredit/ColorEditPopup.java |  70 +++++
 .../mod/config/types/coloredit/ColorWheel.java     | 147 ++++++++++
 .../mod/config/types/coloredit/ValueBar.java       | 150 ++++++++++
 .../mod/features/AbstractFeature.java              |  36 +--
 .../mod/features/AbstractHUDFeature.java           |  55 +++-
 .../mod/features/FeatureParameter.java             |  33 ++-
 .../mod/features/FeatureRegistry.java              |  13 +-
 .../impl/advanced/FeatureDebuggableMap.java        |   6 -
 .../features/impl/advanced/FeatureTestPeople.java  |   3 +-
 .../mod/features/impl/boss/FeatureBossHealth.java  |   7 +-
 .../features/impl/boss/FeatureBoxRealLivid.java    |   3 +-
 .../mod/features/impl/boss/FeatureHideAnimals.java |  11 +-
 .../features/impl/boss/FeatureWarningOnPortal.java |  27 +-
 .../impl/cosmetics/FeatureNicknameColor.java       |  11 +-
 .../impl/cosmetics/FeatureNicknamePrefix.java      |  12 +-
 .../discord/inviteViewer/PartyInviteViewer.java    |   5 +-
 .../impl/discord/onlinealarm/PlayingDGAlarm.java   |   2 -
 .../mod/features/impl/dungeon/FeatureBoxBats.java  |   6 +-
 .../impl/dungeon/FeatureBoxSkelemaster.java        |   6 +-
 .../features/impl/dungeon/FeatureBoxStarMobs.java  |   6 +-
 .../features/impl/dungeon/FeatureDungeonMap.java   |  32 +--
 .../features/impl/dungeon/FeatureDungeonScore.java |   3 +-
 .../dungeon/FeaturePressAnyKeyToCloseChest.java    |   3 +-
 .../impl/dungeon/FeatureWarnLowHealth.java         |   3 +-
 .../impl/etc/FeatureDecreaseExplosionSound.java    |   3 +-
 .../features/impl/etc/FeatureDisableMessage.java   |   3 +-
 .../features/impl/etc/FeatureEpicCountdown.java    |   5 +-
 .../features/impl/etc/FeatureRepartyCommand.java   |   3 +-
 .../mod/features/impl/etc/FeatureTooltipPrice.java |   3 +-
 .../impl/etc/ability/FeatureAbilityCooldown.java   |   6 +-
 .../mod/features/impl/party/APIKey.java            |   3 +-
 .../impl/party/customgui/PanelPartyFinder.java     |  16 +-
 .../FeatureViewPlayerStatsOnJoin.java              |  30 +-
 .../impl/party/playerpreview/api/SkinFetcher.java  |   1 -
 .../playerpreview/widget/WidgetProfileViewer.java  |   2 -
 .../widget/WidgetProfileViewerData.java            |   3 -
 .../mod/features/impl/secret/FeatureBloodRush.java |   3 +-
 .../impl/secret/FeatureCreateRefreshLine.java      |  34 +--
 .../impl/secret/FeatureFreezePathfind.java         |   3 +-
 .../impl/secret/FeaturePathfindStrategy.java       |  62 +---
 .../features/impl/secret/FeaturePathfindToAll.java |   9 +-
 .../impl/secret/FeatureSoulRoomWarning.java        | 192 +++++--------
 .../impl/secret/FeatureTogglePathfind.java         |   3 +-
 .../impl/secret/PathfindLineProperties.java        |  45 +--
 .../mechanicbrowser/FeatureMechanicBrowse.java     |  11 +-
 .../features/impl/solvers/FeatureSolverBlaze.java  |   9 +-
 .../impl/solvers/FeatureSolverBombdefuse.java      |   3 +-
 .../features/impl/solvers/FeatureSolverBox.java    |  15 +-
 .../impl/solvers/FeatureSolverIcefill.java         |   6 +-
 .../features/impl/solvers/FeatureSolverKahoot.java |   3 +-
 .../features/impl/solvers/FeatureSolverRiddle.java |   3 +-
 .../impl/solvers/FeatureSolverSilverfish.java      |   6 +-
 .../impl/solvers/FeatureSolverTeleport.java        |   5 +-
 .../impl/solvers/FeatureSolverTictactoe.java       |   5 +-
 .../mod/features/text/TextHUDFeature.java          |  77 +----
 .../kr/syeyoung/dungeonsguide/mod/gui/MPanel.java  |   3 +-
 .../dungeonsguide/mod/guiv2/elements/AbsXY.java    |   2 +-
 .../dungeonsguide/mod/guiv2/elements/Border.java   |   2 +-
 .../mod/guiv2/elements/CompatLayer.java            | 169 +++++++++++
 .../mod/guiv2/elements/NegativeStencil.java        | 112 ++++++++
 .../mod/guiv2/elements/TextField.java              |   1 +
 .../guiv2/elements/popups/AbsLocationPopup.java    |  16 +-
 .../mod/guiv2/renderer/RenderingContext.java       |   4 +
 .../mod/guiv2/xml/DomElementRegistry.java          |   1 +
 .../dungeonsguide/gui/config/normalconfig.gui      |   4 +-
 .../dungeonsguide/gui/config/parameter/boolean.gui |  22 ++
 .../dungeonsguide/gui/config/parameter/color.gui   |  25 ++
 .../gui/config/parameter/colorSet.gui              |  85 ++++++
 .../dungeonsguide/gui/config/parameter/keybind.gui |  23 ++
 .../dungeonsguide/gui/config/parameter/number.gui  |  46 +++
 .../dungeonsguide/gui/config/parameter/string.gui  |  22 ++
 .../gui/config/parameter/stringChoice.gui          |  50 ++++
 .../dungeonsguide/gui/config/parameteritem.gui     |  60 ++++
 .../dungeonsguide/gui/config/popup/quickEdit.gui   |  23 ++
 .../dungeonsguide/gui/config/popup/quickEnable.gui |  34 +++
 .../assets/dungeonsguide/gui/config/popupmenu.gui  |   2 +-
 .../dungeonsguide/gui/elements/locationedPopup.gui |  10 +-
 .../gui/features/fairysoul/roomconfiguration.gui   |  49 ++++
 .../gui/features/fairysoul/roomswitch.gui          |  34 +++
 .../assets/dungeonsguide/shaders/chromacircle.frag |  27 ++
 .../dungeonsguide/shaders/chromaroundrect.frag     |  23 ++
 .../dungeonsguide/shaders/chromaroundrect.vert     |  19 ++
 .../assets/dungeonsguide/shaders/donut.frag        |  17 ++
 .../assets/dungeonsguide/shaders/roundrect.frag    |   6 +-
 .../assets/dungeonsguide/shaders/roundrect.vert    |   8 +
 120 files changed, 2489 insertions(+), 2002 deletions(-)
 delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/ConfigPanelCreator.java
 delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/GuiConfigV2.java
 delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/MCategory.java
 delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/MCategoryElement.java
 delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/MFeature.java
 delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/MFeatureEdit.java
 delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/MNotFound.java
 delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/MPanelCategory.java
 delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/MParameterEdit.java
 delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/NestedCategory.java
 delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/RootConfigPanel.java
 create mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/configv3/ParameterItem.java
 create mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/FeatureTypeHandler.java
 delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCColor.java
 create mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCEnum.java
 delete mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TypeConverter.java
 create mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/coloredit/AlphaBar.java
 create mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/coloredit/ChromaBar.java
 create mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/coloredit/ColorEditPopup.java
 create mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/coloredit/ColorWheel.java
 create mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/coloredit/ValueBar.java
 create mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/CompatLayer.java
 create mode 100644 mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/NegativeStencil.java
 create mode 100644 mod/src/main/resources/assets/dungeonsguide/gui/config/parameter/boolean.gui
 create mode 100644 mod/src/main/resources/assets/dungeonsguide/gui/config/parameter/color.gui
 create mode 100644 mod/src/main/resources/assets/dungeonsguide/gui/config/parameter/colorSet.gui
 create mode 100644 mod/src/main/resources/assets/dungeonsguide/gui/config/parameter/keybind.gui
 create mode 100644 mod/src/main/resources/assets/dungeonsguide/gui/config/parameter/number.gui
 create mode 100644 mod/src/main/resources/assets/dungeonsguide/gui/config/parameter/string.gui
 create mode 100644 mod/src/main/resources/assets/dungeonsguide/gui/config/parameter/stringChoice.gui
 create mode 100644 mod/src/main/resources/assets/dungeonsguide/gui/config/parameteritem.gui
 create mode 100644 mod/src/main/resources/assets/dungeonsguide/gui/config/popup/quickEdit.gui
 create mode 100644 mod/src/main/resources/assets/dungeonsguide/gui/config/popup/quickEnable.gui
 create mode 100644 mod/src/main/resources/assets/dungeonsguide/gui/features/fairysoul/roomconfiguration.gui
 create mode 100644 mod/src/main/resources/assets/dungeonsguide/gui/features/fairysoul/roomswitch.gui
 create mode 100644 mod/src/main/resources/assets/dungeonsguide/shaders/chromacircle.frag
 create mode 100644 mod/src/main/resources/assets/dungeonsguide/shaders/chromaroundrect.frag
 create mode 100644 mod/src/main/resources/assets/dungeonsguide/shaders/chromaroundrect.vert
 create mode 100644 mod/src/main/resources/assets/dungeonsguide/shaders/donut.frag
 create mode 100644 mod/src/main/resources/assets/dungeonsguide/shaders/roundrect.vert

(limited to 'mod')

diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/commands/CommandDgDebug.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/commands/CommandDgDebug.java
index 7bd4d489..239ee14e 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/commands/CommandDgDebug.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/commands/CommandDgDebug.java
@@ -26,7 +26,6 @@ import kr.syeyoung.dungeonsguide.launcher.Main;
 import kr.syeyoung.dungeonsguide.mod.DungeonsGuide;
 import kr.syeyoung.dungeonsguide.mod.SkyblockStatus;
 import kr.syeyoung.dungeonsguide.mod.chat.ChatTransmitter;
-import kr.syeyoung.dungeonsguide.mod.config.guiconfig.NestedCategory;
 import kr.syeyoung.dungeonsguide.mod.dungeon.DungeonContext;
 import kr.syeyoung.dungeonsguide.mod.dungeon.events.DungeonEventHolder;
 import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom;
@@ -57,7 +56,6 @@ import net.minecraft.util.BlockPos;
 import net.minecraft.util.ChatComponentText;
 import net.minecraft.util.Tuple;
 import net.minecraftforge.common.MinecraftForge;
-import org.lwjgl.opengl.*;
 
 import javax.crypto.BadPaddingException;
 import javax.crypto.IllegalBlockSizeException;
@@ -558,54 +556,54 @@ public class CommandDgDebug extends CommandBase {
     }
 
     private void dumpSettingsCommand() {
-        NestedCategory nestedCategory = new NestedCategory("ROOT");
-        for (AbstractFeature abstractFeature : FeatureRegistry.getFeatureList()) {
-            String category = abstractFeature.getCategory();
-            NestedCategory currentRoot = nestedCategory;
-            for (String s : category.split("\\.")) {
-                NestedCategory finalCurrentRoot = currentRoot;
-                if (currentRoot.children().containsKey(s)) {
-                    currentRoot = currentRoot.children().get(s);
-                } else {
-                    currentRoot.child(currentRoot = new NestedCategory(finalCurrentRoot.categoryFull() + "." + s));
-                }
-            }
-        }
-
-        StringBuilder stringBuilder = new StringBuilder();
-        StringBuilder stringBuilder2 = new StringBuilder();
-
-        Stack<Tuple<NestedCategory, Integer>> stak = new Stack<>();
-        stak.push(new Tuple<>(nestedCategory, 0));
-        Set<NestedCategory> discovered = new HashSet<>();
-        while (!stak.isEmpty()) {
-            Tuple<NestedCategory, Integer> n = stak.pop();
-            if (discovered.contains(n.getFirst())) {
-                continue;
-            }
-            discovered.add(n.getFirst());
-            for (Map.Entry<String, NestedCategory> stringNestedCategoryEntry : n.getFirst().children().entrySet()) {
-                stak.push(new Tuple<>(stringNestedCategoryEntry.getValue(), n.getSecond() + 1));
-            }
-
-            if (n.getFirst().categoryFull().equals("ROOT")) {
-                continue;
-            }
-
-            String prefix = "";
-            for (int i = 0; i < n.getSecond() - 1; i++) {
-                prefix += "    ";
-            }
-
-            List<AbstractFeature> abstractFeatureList = FeatureRegistry.getFeaturesByCategory().getOrDefault(n.getFirst().categoryFull().substring(5), Collections.emptyList());
-            stringBuilder.append(prefix).append("- C ").append(n.getFirst().categoryFull()).append("\n");
-            stringBuilder2.append(n.getFirst().categoryFull()).append("\n");
-            for (AbstractFeature abstractFeature : abstractFeatureList) {
-                stringBuilder.append(prefix).append("    - F ").append(abstractFeature.getName()).append(" / ").append(abstractFeature.getDescription().replace("\n", "$NEW_LINE$")).append("\n");
-            }
-        }
-        System.out.println(stringBuilder.toString());
-        System.out.println(stringBuilder2.toString());
+//        NestedCategory nestedCategory = new NestedCategory("ROOT");
+//        for (AbstractFeature abstractFeature : FeatureRegistry.getFeatureList()) {
+//            String category = abstractFeature.getCategory();
+//            NestedCategory currentRoot = nestedCategory;
+//            for (String s : category.split("\\.")) {
+//                NestedCategory finalCurrentRoot = currentRoot;
+//                if (currentRoot.children().containsKey(s)) {
+//                    currentRoot = currentRoot.children().get(s);
+//                } else {
+//                    currentRoot.child(currentRoot = new NestedCategory(finalCurrentRoot.categoryFull() + "." + s));
+//                }
+//            }
+//        }
+//
+//        StringBuilder stringBuilder = new StringBuilder();
+//        StringBuilder stringBuilder2 = new StringBuilder();
+//
+//        Stack<Tuple<NestedCategory, Integer>> stak = new Stack<>();
+//        stak.push(new Tuple<>(nestedCategory, 0));
+//        Set<NestedCategory> discovered = new HashSet<>();
+//        while (!stak.isEmpty()) {
+//            Tuple<NestedCategory, Integer> n = stak.pop();
+//            if (discovered.contains(n.getFirst())) {
+//                continue;
+//            }
+//            discovered.add(n.getFirst());
+//            for (Map.Entry<String, NestedCategory> stringNestedCategoryEntry : n.getFirst().children().entrySet()) {
+//                stak.push(new Tuple<>(stringNestedCategoryEntry.getValue(), n.getSecond() + 1));
+//            }
+//
+//            if (n.getFirst().categoryFull().equals("ROOT")) {
+//                continue;
+//            }
+//
+//            String prefix = "";
+//            for (int i = 0; i < n.getSecond() - 1; i++) {
+//                prefix += "    ";
+//            }
+//
+//            List<AbstractFeature> abstractFeatureList = FeatureRegistry.getFeaturesByCategory().getOrDefault(n.getFirst().categoryFull().substring(5), Collections.emptyList());
+//            stringBuilder.append(prefix).append("- C ").append(n.getFirst().categoryFull()).append("\n");
+//            stringBuilder2.append(n.getFirst().categoryFull()).append("\n");
+//            for (AbstractFeature abstractFeature : abstractFeatureList) {
+//                stringBuilder.append(prefix).append("    - F ").append(abstractFeature.getName()).append(" / ").append(abstractFeature.getDescription().replace("\n", "$NEW_LINE$")).append("\n");
+//            }
+//        }
+//        System.out.println(stringBuilder.toString());
+//        System.out.println(stringBuilder2.toString());
     }
 
     private void readMapCommand(String[] args) {
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/commands/CommandDungeonsGuide.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/commands/CommandDungeonsGuide.java
index c40a0a80..fed67faf 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/commands/CommandDungeonsGuide.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/commands/CommandDungeonsGuide.java
@@ -22,7 +22,6 @@ import com.mojang.authlib.GameProfile;
 import kr.syeyoung.dungeonsguide.launcher.Main;
 import kr.syeyoung.dungeonsguide.mod.DungeonsGuide;
 import kr.syeyoung.dungeonsguide.mod.chat.ChatTransmitter;
-import kr.syeyoung.dungeonsguide.mod.config.guiconfig.GuiConfigV2;
 import kr.syeyoung.dungeonsguide.mod.config.guiconfig.configv3.MainConfigWidget;
 import kr.syeyoung.dungeonsguide.mod.config.guiconfig.location2.HUDLocationConfig;
 import kr.syeyoung.dungeonsguide.mod.cosmetics.CosmeticsManager;
@@ -92,7 +91,7 @@ public class CommandDungeonsGuide extends CommandBase {
     public void processCommand(ICommandSender sender, String[] args) {
 
         if (args.length == 0) {
-            target = new GuiConfigV2();
+            target = new GuiScreenAdapter(new GlobalHUDScale(new MainConfigWidget()));
             return;
         }
 
@@ -104,9 +103,6 @@ public class CommandDungeonsGuide extends CommandBase {
             case "gui":
                 target = new GuiScreenAdapter(new GlobalHUDScale(new HUDLocationConfig(null)));
                 break;
-            case "v3":
-                target = new GuiScreenAdapter(new GlobalHUDScale(new MainConfigWidget()));
-                break;
             case "pv":
                 pvCommand(args[1], sender); //args[1] is the player name
                 break;
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/ConfigPanelCreator.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/ConfigPanelCreator.java
deleted file mode 100644
index da3974a3..00000000
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/ConfigPanelCreator.java
+++ /dev/null
@@ -1,40 +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.mod.config.guiconfig;
-
-import com.google.common.base.Function;
-import com.google.common.base.Supplier;
-import kr.syeyoung.dungeonsguide.mod.gui.MPanel;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public class ConfigPanelCreator implements Function<String, MPanel> {
-    public static final ConfigPanelCreator INSTANCE = new ConfigPanelCreator();
-
-    public static final Map<String, Supplier<MPanel>> map = new HashMap<String, Supplier<MPanel>>();
-
-    @Nullable
-    @Override
-    public MPanel apply(@Nullable String input) {
-        if (!map.containsKey(input)) return null;
-        return map.get(input).get();
-    }
-}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/GuiConfigV2.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/GuiConfigV2.java
deleted file mode 100644
index 0f6be522..00000000
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/GuiConfigV2.java
+++ /dev/null
@@ -1,59 +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.mod.config.guiconfig;
-
-import kr.syeyoung.dungeonsguide.mod.gui.MGui;
-import lombok.Getter;
-import net.minecraft.client.Minecraft;
-import net.minecraft.util.MathHelper;
-
-import java.awt.*;
-
-public class GuiConfigV2 extends MGui {
-
-    @Getter
-    private RootConfigPanel rootConfigPanel;
-
-    public GuiConfigV2() {
-        rootConfigPanel = new RootConfigPanel(this);
-        getMainPanel().add(rootConfigPanel);
-    }
-
-
-    @Override
-    public void initGui() {
-        super.initGui();
-        int dw = Minecraft.getMinecraft().displayWidth;
-        int dh = Minecraft.getMinecraft().displayHeight;
-        int width = MathHelper.clamp_int(dw - 200, 1250, 1500), height = MathHelper.clamp_int(dh - 200, 600, 800);
-        double scale = 2.0;
-        if (dw <= width || dh <= height) {
-            width = width/2; height = height/2;
-            scale = 1.0;
-        }
-        rootConfigPanel.setBounds(new Rectangle((dw-width)/2, (dh-height)/2, width,height));
-        rootConfigPanel.setScale(scale);
-    }
-
-    @Override
-    public void drawScreen(int mouseX, int mouseY, float partialTicks) {
-        super.drawDefaultBackground();
-        super.drawScreen(mouseX, mouseY, partialTicks);
-    }
-}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/MCategory.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/MCategory.java
deleted file mode 100644
index c4561c09..00000000
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/MCategory.java
+++ /dev/null
@@ -1,103 +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.mod.config.guiconfig;
-
-import kr.syeyoung.dungeonsguide.mod.features.FeatureRegistry;
-import kr.syeyoung.dungeonsguide.mod.gui.MPanel;
-import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils;
-import kr.syeyoung.dungeonsguide.mod.utils.cursor.EnumCursor;
-import lombok.Getter;
-import lombok.Setter;
-import net.minecraft.client.Minecraft;
-import net.minecraft.client.audio.PositionedSoundRecord;
-import net.minecraft.client.gui.FontRenderer;
-import net.minecraft.client.gui.Gui;
-import net.minecraft.client.renderer.GlStateManager;
-import net.minecraft.util.ResourceLocation;
-import org.lwjgl.opengl.GL11;
-import org.lwjgl.opengl.GL14;
-
-import java.awt.*;
-
-public class MCategory extends MPanel {
-
-    private NestedCategory nestedCategory;
-    private RootConfigPanel rootConfigPanel;
-    @Getter
-    @Setter
-    private Color hover = new Color(94, 94, 94, 255);
-    public MCategory(NestedCategory nestedCategory, RootConfigPanel rootConfigPanel) {
-        this.nestedCategory = nestedCategory;
-        this.rootConfigPanel = rootConfigPanel;
-    }
-
-    @Override
-    public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) {
-        int border = RenderUtils.blendAlpha(0x141414, 0.12f);
-        if (!rootConfigPanel.getSearchWord().isEmpty() && (nestedCategory.categoryName().toLowerCase().contains(rootConfigPanel.getSearchWord()))) {
-            border = 0xFF02EE67;
-        }
-
-        Gui.drawRect(0,0,getBounds().width, getBounds().height,border);
-        if (getBounds().height >= 28)
-            Gui.drawRect(1,18,getBounds().width -1, getBounds().height-1, RenderUtils.blendAlpha(0x141414, 0.15f));
-        Gui.drawRect(1,1,getBounds().width-1, 18, RenderUtils.blendAlpha(0x141414, 0.12f));
-
-
-        FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
-        GlStateManager.pushMatrix();
-        GlStateManager.translate(5,5,0);
-        GlStateManager.scale(1.0,1.0,0);
-        GlStateManager.enableBlend();
-        GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
-        GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
-
-        fr.drawString((lastAbsClip.contains(absMousex, absMousey) ? "§n" : "") + nestedCategory.categoryName(), 0,0, 0xFFFFFFFF);
-        GlStateManager.popMatrix();
-
-        fr.drawSplitString(FeatureRegistry.getCategoryDescription().getOrDefault(nestedCategory.categoryFull(), ""), 5, 23, getBounds().width -10, 0xFFBFBFBF);
-    }
-
-
-    @Override
-    public Dimension getPreferredSize() {
-        FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
-
-        int descriptionHeight =
-                FeatureRegistry.getCategoryDescription().containsKey(nestedCategory.categoryFull()) ?
-                fr.listFormattedStringToWidth(FeatureRegistry.getCategoryDescription().get(nestedCategory.categoryFull()), Math.max(100, getBounds().width - 10)).size() * fr.FONT_HEIGHT
-                : -9;
-
-        return new Dimension(100, descriptionHeight + 28);
-    }
-
-    @Override
-    public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) {
-        if (lastAbsClip.contains(absMouseX, absMouseY)) {
-            Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F));
-            rootConfigPanel.setCurrentPageAndPushHistory(nestedCategory.categoryFull());
-        }
-    }
-
-    @Override
-    public void mouseMoved(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0) {
-        if (lastAbsClip.contains(absMouseX, absMouseY))
-            setCursor(EnumCursor.POINTING_HAND);
-    }
-}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/MCategoryElement.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/MCategoryElement.java
deleted file mode 100644
index af23d306..00000000
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/MCategoryElement.java
+++ /dev/null
@@ -1,82 +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.mod.config.guiconfig;
-
-import kr.syeyoung.dungeonsguide.mod.gui.MPanel;
-import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils;
-import kr.syeyoung.dungeonsguide.mod.utils.cursor.EnumCursor;
-import net.minecraft.client.Minecraft;
-import net.minecraft.client.audio.PositionedSoundRecord;
-import net.minecraft.client.gui.FontRenderer;
-import net.minecraft.client.gui.Gui;
-import net.minecraft.util.ResourceLocation;
-
-import java.awt.*;
-
-public class MCategoryElement extends MPanel {
-    private String category;
-    private Runnable onClick;
-    private int leftPad = 0;
-    private int offsetX;
-    private RootConfigPanel rootConfigPanel;
-    public MCategoryElement(String category, Runnable onClick, int leftPad, int offsetX, RootConfigPanel root) {
-        this.category = category;
-        this.onClick = onClick;
-        this.leftPad = leftPad;
-        this.offsetX = offsetX;
-        this.rootConfigPanel = root;
-    }
-
-    @Override
-    public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) {
-        if (rootConfigPanel.getCurrentPage().equals(category)) {
-            clip(0,scissor.y, Minecraft.getMinecraft().displayWidth, scissor.height);
-            Gui.drawRect(leftPad - offsetX, 0, getBounds().width, getBounds().height, RenderUtils.blendAlpha(0x141414, 0.13f));
-        } else if (lastAbsClip.contains(absMousex, absMousey) && getTooltipsOpen() == 0) {
-            clip(0,scissor.y, Minecraft.getMinecraft().displayWidth, scissor.height);
-            Gui.drawRect(leftPad - offsetX, 0, getBounds().width, getBounds().height, RenderUtils.blendAlpha(0x141414, 0.09f));
-        }
-        clip(scissor.x, scissor.y, scissor.width, scissor.height);
-
-
-        FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
-        String name = category.substring(category.lastIndexOf(".")+1);
-        fr.drawString(name, leftPad,2,-1);
-
-    }
-
-    @Override
-    public Dimension getPreferredSize() {
-        FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
-        return new Dimension(fr.getStringWidth(category.substring(category.lastIndexOf(".")+1)) + leftPad+10, fr.FONT_HEIGHT+4);
-    }
-
-    @Override
-    public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) {
-        if (!lastAbsClip.contains(absMouseX, absMouseY) || getTooltipsOpen() > 0) { return; }
-        if (onClick != null) onClick.run();
-        Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F));
-
-    }
-    @Override
-    public void mouseMoved(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0) {
-        if (lastAbsClip.contains(absMouseX, absMouseY))
-            setCursor(EnumCursor.POINTING_HAND);
-    }
-}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/MFeature.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/MFeature.java
deleted file mode 100644
index 9cb6c946..00000000
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/MFeature.java
+++ /dev/null
@@ -1,153 +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.mod.config.guiconfig;
-
-import kr.syeyoung.dungeonsguide.mod.features.AbstractFeature;
-import kr.syeyoung.dungeonsguide.mod.features.RawRenderingGuiFeature;
-import kr.syeyoung.dungeonsguide.mod.gui.MPanel;
-import kr.syeyoung.dungeonsguide.mod.gui.elements.MButton;
-import kr.syeyoung.dungeonsguide.mod.gui.elements.MToggleButton;
-import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils;
-import lombok.Getter;
-import lombok.Setter;
-import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.FontRenderer;
-import net.minecraft.client.gui.Gui;
-import net.minecraft.client.renderer.GlStateManager;
-import org.lwjgl.opengl.GL11;
-import org.lwjgl.opengl.GL14;
-
-import java.awt.*;
-import java.util.ArrayList;
-import java.util.List;
-
-public class MFeature extends MPanel {
-
-    @Getter
-    private final AbstractFeature feature;
-
-    private final List<MPanel> addons =  new ArrayList<MPanel>();
-
-    @Getter @Setter
-    private Color hover;
-
-    private final RootConfigPanel panel;
-
-    public MFeature(final AbstractFeature abstractFeature, final RootConfigPanel panel) {
-        this.panel = panel;
-        this.feature = abstractFeature;
-
-        if (abstractFeature.isDisyllable()) {
-            final MToggleButton mStringSelectionButton = new MToggleButton();
-            mStringSelectionButton.setOnToggle(new Runnable() {
-                @Override
-                public void run() {
-                    boolean selected = mStringSelectionButton.isEnabled();
-                    feature.setEnabled(selected);
-                }
-            });
-            mStringSelectionButton.setBackground(RenderUtils.blendAlpha(0x141414, 0.07f));
-            addons.add(mStringSelectionButton);
-            mStringSelectionButton.setEnabled(feature.isEnabled());
-            mStringSelectionButton.setSize(new Dimension(40, 15));
-            add(mStringSelectionButton);
-        }
-        if (abstractFeature.getParameters().size() != 0) {
-            MButton button = new MButton();
-            button.setText("Settings");
-            button.setOnActionPerformed(new Runnable() {
-                @Override
-                public void run() {
-                    panel.setCurrentPageAndPushHistory(abstractFeature.getEditRoute(panel));
-                }
-            });
-            button.setBackground(RenderUtils.blendAlpha(0x141414, 0.07f));
-            button.setClicked(RenderUtils.blendAlpha(0x141414, 0.17f));
-            button.setHover(RenderUtils.blendAlpha(0x141414, 0.17f));
-            addons.add(button);
-            button.setSize(new Dimension(50, 15));
-            add(button);
-        }
-        if (abstractFeature instanceof RawRenderingGuiFeature) {
-            MButton button = new MButton();
-            button.setText("Relocate");
-            button.setOnActionPerformed(new Runnable() {
-                @Override
-                public void run() {
-//                    Minecraft.getMinecraft().displayGuiScreen(new GuiGuiLocationConfig(Minecraft.getMinecraft().currentScreen, abstractFeature));
-                    button.setBeingClicked(false);
-                }
-            });
-            button.setBackground(RenderUtils.blendAlpha(0x141414, 0.07f));
-            button.setClicked(RenderUtils.blendAlpha(0x141414, 0.17f));
-            button.setHover(RenderUtils.blendAlpha(0x141414, 0.17f));
-            addons.add(button);
-            button.setSize(new Dimension(75, 15));
-            add(button);
-        }
-    }
-
-    @Override
-    public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) {
-
-        int border = RenderUtils.blendAlpha(0x141414, 0.12f);
-        if (!panel.getSearchWord().isEmpty() && (feature.getName().toLowerCase().contains(panel.getSearchWord()) || feature.getDescription().toLowerCase().contains(panel.getSearchWord()))) {
-            border = 0xFF02EE67;
-        }
-
-        Gui.drawRect(0,0,getBounds().width, getBounds().height,border);
-        Gui.drawRect(1,18,getBounds().width -1, getBounds().height-1, RenderUtils.blendAlpha(0x141414, 0.15f));
-        Gui.drawRect(1,1,getBounds().width-1, 18, RenderUtils.blendAlpha(0x141414, 0.12f));
-
-
-        FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
-        GlStateManager.pushMatrix();
-        GlStateManager.translate(5,5,0);
-        GlStateManager.scale(1.0,1.0,0);
-        GlStateManager.enableBlend();
-        GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
-        GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
-        fr.drawString(feature.getName(), 0,0, 0xFFFFFFFF);
-        GlStateManager.popMatrix();
-
-        fr.drawSplitString(feature.getDescription(), 5, 23, getBounds().width -10, 0xFFBFBFBF);
-    }
-
-    @Override
-    public void resize(int parentWidth, int parentHeight) {
-        this.setSize(new Dimension(parentWidth, getBounds().height));
-    }
-
-    @Override
-    public Dimension getPreferredSize() {
-        FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
-        int descriptionHeight = fr.listFormattedStringToWidth(feature.getDescription(), Math.max(100, getBounds().width - 10)).size() * fr.FONT_HEIGHT;
-
-        return new Dimension(100, descriptionHeight + 28);
-    }
-
-    @Override
-    public void onBoundsUpdate() {
-        int x = getBounds().width - 5;
-        for (MPanel panel : addons) {
-            panel.setBounds(new Rectangle(x - panel.getPreferredSize().width, 3, panel.getPreferredSize().width, 12));
-            x -= panel.getPreferredSize().width + 5;
-        }
-    }
-}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/MFeatureEdit.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/MFeatureEdit.java
deleted file mode 100644
index c7a1e6ab..00000000
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/MFeatureEdit.java
+++ /dev/null
@@ -1,114 +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.mod.config.guiconfig;
-
-
-import kr.syeyoung.dungeonsguide.mod.features.AbstractFeature;
-import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
-import kr.syeyoung.dungeonsguide.mod.gui.MPanel;
-import kr.syeyoung.dungeonsguide.mod.gui.elements.MButton;
-import kr.syeyoung.dungeonsguide.mod.gui.elements.MList;
-import kr.syeyoung.dungeonsguide.mod.gui.elements.MModalConfirmation;
-
-import java.awt.*;
-import java.util.HashMap;
-import java.util.Map;
-
-public class MFeatureEdit extends MPanel {
-    private MList list;
-    private MButton goBack, resetToDefault;
-    private RootConfigPanel rootConfigPanel;
-    private AbstractFeature abstractFeature;
-
-    private Map<String, MPanel> parameterEdits = new HashMap<>();
-
-    public MFeatureEdit(AbstractFeature abstractFeature, RootConfigPanel rootConfigPanel) {
-        this.abstractFeature = abstractFeature;
-        this.rootConfigPanel = rootConfigPanel;
-        list = new MList();
-        list.setGap(5);
-        list.setDrawLine(false);
-        add(list);
-
-        goBack = new MButton();
-        goBack.setText("< Go Back");
-        goBack.setOnActionPerformed(rootConfigPanel::goBack);
-        add(goBack);
-        resetToDefault = new MButton();
-        resetToDefault.setText("Reset To Default");
-        resetToDefault.setForeground(Color.red);
-        resetToDefault.setOnActionPerformed(() -> {
-            openResetConfirmation();
-        });
-        add(resetToDefault);
-    }
-
-    public void openResetConfirmation() {
-        MModalConfirmation mModal = new MModalConfirmation("Are you sure?",
-                "Resetting to default will reset your configuration for the selected feature to default",
-                () -> {
-            for (FeatureParameter parameter : abstractFeature.getParameters()) {
-                parameter.setToDefault();
-            }
-            abstractFeature.onParameterReset();
-            rootConfigPanel.invalidatePage(abstractFeature.getEditRoute(rootConfigPanel));
-            }, () -> {});
-        mModal.setScale(getScale());
-        mModal.getYes().setBorder(0xFFFF0000);
-        mModal.getYes().setText("Yes, Reset it");
-        mModal.getNo().setText("Cancel");
-        mModal.open(MFeatureEdit.this);
-    }
-
-    public void addParameterEdit(String name, MPanel paramEdit) {
-        parameterEdits.put(name, paramEdit);
-        list.add(paramEdit);
-    }
-    public MPanel removeParameterEdit(String name) {
-        MPanel panel = parameterEdits.remove(name);
-        list.remove(panel);
-        return panel;
-    }
-
-    @Override
-    public void resize(int parentWidth, int parentHeight) {
-        super.resize(parentWidth, parentHeight);
-        setBounds(new Rectangle(0,0,parentWidth,parentHeight));
-        Dimension prefSize = getPreferredSize();
-        int hei = prefSize.height;
-        setBounds(new Rectangle(0,0,parentWidth,hei));
-    }
-
-    @Override
-    public void setBounds(Rectangle bounds) {
-        super.setBounds(bounds);
-        goBack.setBounds(new Rectangle(5,5,75,15));
-        resetToDefault.setBounds(new Rectangle(bounds.width - 105, 5, 100, 15));
-
-        list.setBounds(new Rectangle(5,25,bounds.width - 10, bounds.height - 10));
-        list.realignChildren();
-
-    }
-
-    @Override
-    public Dimension getPreferredSize() {
-        Dimension listPref = list.getPreferredSize();
-        return new Dimension(listPref.width + 10, listPref.height + 30);
-    }
-}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/MNotFound.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/MNotFound.java
deleted file mode 100644
index b63c4e90..00000000
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/MNotFound.java
+++ /dev/null
@@ -1,38 +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.mod.config.guiconfig;
-
-import kr.syeyoung.dungeonsguide.mod.gui.MPanel;
-import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.FontRenderer;
-
-import java.awt.*;
-
-public class MNotFound extends MPanel {
-    @Override
-    public void resize(int parentWidth, int parentHeight) {
-        setBounds(new Rectangle(0,0,parentWidth,parentHeight));
-    }
-
-    @Override
-    public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) {
-        FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
-        fr.drawString("404 Not Found", (getBounds().width - fr.getStringWidth("404 Not Found")) / 2, (getBounds().height - fr.FONT_HEIGHT) / 2, -1);
-    }
-}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/MPanelCategory.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/MPanelCategory.java
deleted file mode 100644
index 435940d3..00000000
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/MPanelCategory.java
+++ /dev/null
@@ -1,83 +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.mod.config.guiconfig;
-
-import kr.syeyoung.dungeonsguide.mod.features.AbstractFeature;
-import kr.syeyoung.dungeonsguide.mod.features.FeatureRegistry;
-import kr.syeyoung.dungeonsguide.mod.gui.MPanel;
-import kr.syeyoung.dungeonsguide.mod.gui.elements.MList;
-
-import java.awt.*;
-
-public class MPanelCategory extends MPanel {
-
-    private NestedCategory key;
-    private RootConfigPanel rootConfigPanel;
-
-    private MList list;
-
-    public MPanelCategory(NestedCategory nestedCategory, RootConfigPanel rootConfigPanel) {
-        this.key = nestedCategory;
-        this.rootConfigPanel = rootConfigPanel;
-
-        list = new MList();
-        list.setDrawLine(false);
-        list.setGap(5);
-        add(list);
-
-        for (NestedCategory value : nestedCategory.children().values()) {
-            list.add(new MCategory(value, rootConfigPanel));
-        }
-        if (nestedCategory.parent() != null) {
-            String actualCategory = nestedCategory.categoryFull().substring(5);
-            if (FeatureRegistry.getFeaturesByCategory().containsKey(actualCategory))
-                for (AbstractFeature abstractFeature : FeatureRegistry.getFeaturesByCategory().get(actualCategory)) {
-                    MFeature mFeature = new MFeature(abstractFeature, rootConfigPanel);
-                    list.add(mFeature);
-                    mFeature.setHover(new Color(94, 94, 94, 255));
-                }
-        }
-        list.realignChildren();
-
-    }
-
-    @Override
-    public void resize(int parentWidth, int parentHeight) {
-        super.resize(parentWidth, parentHeight);
-        setBounds(new Rectangle(0,0,parentWidth,parentHeight));
-        Dimension prefSize = getPreferredSize();
-        int hei = prefSize.height;
-        setBounds(new Rectangle(0,0,parentWidth,hei));
-    }
-
-    @Override
-    public void setBounds(Rectangle bounds) {
-        super.setBounds(bounds);
-        list.setBounds(new Rectangle(5,5,bounds.width- 10, bounds.height - 10));
-        list.realignChildren();
-    }
-
-    @Override
-    public Dimension getPreferredSize() {
-        Dimension prefSize = list.getPreferredSize();
-        int wid = prefSize.width + 10;
-        int hei = prefSize.height + 10;
-        return new Dimension(wid, hei);
-    }
-}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/MParameterEdit.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/MParameterEdit.java
deleted file mode 100644
index 9cf5a6ed..00000000
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/MParameterEdit.java
+++ /dev/null
@@ -1,220 +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.mod.config.guiconfig;
-
-
-import kr.syeyoung.dungeonsguide.mod.config.types.AColor;
-import kr.syeyoung.dungeonsguide.mod.features.AbstractFeature;
-import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
-import kr.syeyoung.dungeonsguide.mod.gui.MPanel;
-import kr.syeyoung.dungeonsguide.mod.gui.elements.*;
-import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils;
-import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.FontRenderer;
-import net.minecraft.client.gui.Gui;
-
-import java.awt.*;
-import java.util.function.Predicate;
-
-public class MParameterEdit extends MPanel {
-    private AbstractFeature abstractFeature;
-    private FeatureParameter featureParameter;
-    private RootConfigPanel rootConfigPanel;
-    private MPanel valueEditHolder;
-    private MPanel valueEdit;
-
-    private Predicate<FeatureParameter> isDisabled ;
-
-    public MParameterEdit(AbstractFeature abstractFeature, FeatureParameter parameter, RootConfigPanel rootConfigPanel) {
-        this(abstractFeature, parameter, rootConfigPanel, (a) -> false);
-    }
-
-    public MParameterEdit(AbstractFeature abstractFeature, FeatureParameter parameter, RootConfigPanel rootConfigPanel, Predicate<FeatureParameter> isDisabled ) {
-        this.abstractFeature = abstractFeature;
-        this.featureParameter = parameter;
-        this.rootConfigPanel = rootConfigPanel;
-        this.isDisabled = isDisabled;
-
-        if (parameter.getValue_type().equals("string")) {
-            valueEdit = new MTextField() {
-                @Override
-                public void edit(String str) {
-                    parameter.setValue(str);
-                }
-            };
-            ((MTextField)valueEdit).setText((String) parameter.getValue());
-        } else if (parameter.getValue_type().equals("integer")) {
-            valueEdit = new MIntegerSelectionButton((Integer) parameter.getValue());
-            ((MIntegerSelectionButton)valueEdit).setOnUpdate(() -> {
-                parameter.setValue(((MIntegerSelectionButton) valueEdit).getData());
-            });
-        } else if (parameter.getValue_type().equals("float")) {
-            valueEdit = new MFloatSelectionButton((Float) parameter.getValue());
-            ((MFloatSelectionButton)valueEdit).setOnUpdate(() -> {
-                parameter.setValue(((MFloatSelectionButton) valueEdit).getData());
-            });
-        } else if (parameter.getValue_type().equals("acolor")) {
-            valueEdit = new MEditableAColor();
-            ((MEditableAColor)valueEdit).setColor((AColor) parameter.getValue());
-            ((MEditableAColor)valueEdit).setEnableEdit(true);
-            ((MEditableAColor)valueEdit).setOnUpdate(() -> {
-                parameter.setValue(((MEditableAColor) valueEdit).getColor());
-            });
-        } else if (parameter.getValue_type().equals("color")) {
-            valueEdit = new MEditableAColor();
-            ((MEditableAColor)valueEdit).setColor(new AColor(((Color) parameter.getValue()).getRGB(), true));
-            ((MEditableAColor)valueEdit).setEnableEdit(true);
-            ((MEditableAColor)valueEdit).setOnUpdate(() -> {
-                parameter.setValue(((MEditableAColor) valueEdit).getColor());
-            });
-        } else if (parameter.getValue_type().equals("boolean")) {
-            valueEdit = new MToggleButton();
-            ((MToggleButton)valueEdit).setEnabled((Boolean) parameter.getValue());
-            ((MToggleButton)valueEdit).setOnToggle(() -> {
-                parameter.setValue(((MToggleButton) valueEdit).isEnabled());
-            });
-        }  else if (parameter.getValue_type().equals("keybind")) {
-            valueEdit = new MKeyEditButton();
-            ((MKeyEditButton)valueEdit).setKey((Integer) parameter.getValue());
-            ((MKeyEditButton)valueEdit).setOnKeyEdit(() -> {
-                parameter.setValue(((MKeyEditButton) valueEdit).getKey());
-            });
-            ((MKeyEditButton)valueEdit).setBorder(RenderUtils.blendTwoColors(0xFF141414,0x7702EE67));
-        }else {
-            valueEdit = new MLabel();
-            ((MLabel)valueEdit).setText("????");
-        }
-
-
-        valueEditHolder = new MPanel() {
-            @Override
-            public void setBounds(Rectangle bounds) {
-                super.setBounds(bounds);
-                Dimension dimension = valueEdit.getPreferredSize();
-                if (dimension.width <= 0) dimension.width = bounds.width/2;
-                if (dimension.height <= 0) dimension.height = bounds.height/2;
-                valueEdit.setBounds(new Rectangle((bounds.width - dimension.width)/2,(bounds.height - dimension.height)/2,dimension.width, dimension.height));
-            }
-        };
-        add(valueEditHolder);
-        valueEditHolder.add(valueEdit);
-    }
-    public MParameterEdit(AbstractFeature abstractFeature, FeatureParameter parameter, RootConfigPanel rootConfigPanel, MPanel valueEdit,  Predicate<FeatureParameter> isDisabled) {
-        this.abstractFeature = abstractFeature;
-        this.featureParameter = parameter;
-        this.rootConfigPanel = rootConfigPanel;
-        this.isDisabled = isDisabled;
-
-
-        valueEditHolder = new MPanel() {
-            @Override
-            public void setBounds(Rectangle bounds) {
-                super.setBounds(bounds);
-                Dimension dimension = valueEdit.getPreferredSize();
-                if (dimension.width <= 0) dimension.width = bounds.width/2;
-                if (dimension.height <= 0) dimension.height = bounds.height/2;
-                valueEdit.setBounds(new Rectangle((bounds.width - dimension.width)/2,(bounds.height - dimension.height)/2,dimension.width, dimension.height));
-            }
-        };
-        add(valueEditHolder);
-        valueEditHolder.add(valueEdit);
-    }
-
-    @Override
-    public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) {
-        Gui.drawRect(0,0,getBounds().width, getBounds().height, RenderUtils.blendAlpha(0x141414, 0.12f));
-        Gui.drawRect(2*bounds.width / 3,1,getBounds().width -1, getBounds().height-1, RenderUtils.blendAlpha(0x141414, 0.15f));
-        Gui.drawRect(4, 15,2*bounds.width / 3-5, 16, RenderUtils.blendAlpha(0x141414, 0.3f));
-
-
-        FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
-        fr.drawString(featureParameter.getName(), 5,5, 0xFFFFFFFF);
-        fr.drawSplitString(featureParameter.getDescription(), 5,18, 2*bounds.width /3-10, 0xFFAAAAAA);
-
-    }
-
-    @Override
-    public void render0(double scale, Point parentPoint, Rectangle parentClip, int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks) {
-        super.render0(scale, parentPoint, parentClip, absMousex, absMousey, relMousex0, relMousey0, partialTicks);
-        if (isDisabled.test(featureParameter)) {
-            Gui.drawRect(0,0, getBounds().width, getBounds().height, 0x55000000);
-        }
-    }
-
-    @Override
-    public Dimension getPreferredSize() {
-        FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
-        int descriptionHeight = fr.listFormattedStringToWidth(featureParameter.getDescription(), Math.max(50, 2*bounds.width/3-10)).size() * fr.FONT_HEIGHT;
-        return new Dimension(100, Math.max(30, descriptionHeight + 23));
-    }
-
-    @Override
-    public void setBounds(Rectangle bounds) {
-        super.setBounds(bounds);
-        valueEditHolder.setBounds(new Rectangle(2*bounds.width / 3, 0, bounds.width / 3, bounds.height));
-    }
-
-    @Override
-    public void keyPressed0(char typedChar, int keyCode) {
-        if (isDisabled.test(featureParameter)) return;
-        super.keyPressed0(typedChar, keyCode);
-    }
-
-    @Override
-    public void keyHeld0(char typedChar, int keyCode) {
-        if (isDisabled.test(featureParameter)) return;
-        super.keyHeld0(typedChar, keyCode);
-    }
-
-    @Override
-    public void keyReleased0(char typedChar, int keyCode) {
-        if (isDisabled.test(featureParameter)) return;
-        super.keyReleased0(typedChar, keyCode);
-    }
-
-    @Override
-    public boolean mouseClicked0(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0, int mouseButton) {
-        if (isDisabled.test(featureParameter)) return false;
-        return super.mouseClicked0(absMouseX, absMouseY, relMouseX0, relMouseY0, mouseButton);
-    }
-
-    @Override
-    public void mouseReleased0(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0, int state) {
-        if (isDisabled.test(featureParameter)) return ;
-        super.mouseReleased0(absMouseX, absMouseY, relMouseX0, relMouseY0, state);
-    }
-
-    @Override
-    public void mouseClickMove0(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0, int clickedMouseButton, long timeSinceLastClick) {
-        if (isDisabled.test(featureParameter)) return ;
-        super.mouseClickMove0(absMouseX, absMouseY, relMouseX0, relMouseY0, clickedMouseButton, timeSinceLastClick);
-    }
-
-    @Override
-    public void mouseScrolled0(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0, int scrollAmount) {
-        if (isDisabled.test(featureParameter)) return ;
-        super.mouseScrolled0(absMouseX, absMouseY, relMouseX0, relMouseY0, scrollAmount);
-    }
-
-    @Override
-    public void mouseMoved0(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0) {
-        if (isDisabled.test(featureParameter)) return ;
-        super.mouseMoved0(absMouseX, absMouseY, relMouseX0, relMouseY0);
-    }
-}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/NestedCategory.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/NestedCategory.java
deleted file mode 100644
index 28a3d4d1..00000000
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/NestedCategory.java
+++ /dev/null
@@ -1,54 +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.mod.config.guiconfig;
-
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.ToString;
-import lombok.experimental.Accessors;
-
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-@Data
-@Accessors(chain = true, fluent = true)
-public
-class NestedCategory {
-    private final String categoryFull;
-    @EqualsAndHashCode.Exclude
-    private String categoryName;
-    @EqualsAndHashCode.Exclude
-    @ToString.Exclude
-    private NestedCategory parent;
-
-    public NestedCategory(String categoryFull) {
-        this.categoryFull = categoryFull;
-        this.categoryName = categoryFull.substring(categoryFull.lastIndexOf(".") + 1);
-    }
-
-    @EqualsAndHashCode.Exclude
-    @ToString.Exclude
-    private Map<String, NestedCategory> children = new LinkedHashMap<>();
-
-    public NestedCategory child(NestedCategory child) {
-        this.children.put(child.categoryName, child);
-        child.parent = this;
-        return this;
-    }
-}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/RootConfigPanel.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/RootConfigPanel.java
deleted file mode 100644
index 6db1a9ae..00000000
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/RootConfigPanel.java
+++ /dev/null
@@ -1,313 +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.mod.config.guiconfig;
-
-import com.google.common.base.Function;
-import kr.syeyoung.dungeonsguide.launcher.auth.AuthManager;
-import kr.syeyoung.dungeonsguide.mod.config.guiconfig.location2.HUDLocationConfig;
-import kr.syeyoung.dungeonsguide.mod.features.AbstractFeature;
-import kr.syeyoung.dungeonsguide.mod.features.FeatureRegistry;
-import kr.syeyoung.dungeonsguide.mod.gui.MPanel;
-import kr.syeyoung.dungeonsguide.mod.gui.elements.*;
-import kr.syeyoung.dungeonsguide.mod.guiv2.GuiScreenAdapter;
-import kr.syeyoung.dungeonsguide.mod.guiv2.elements.GlobalHUDScale;
-import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils;
-import lombok.Getter;
-import lombok.Setter;
-import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.FontRenderer;
-import net.minecraft.client.gui.Gui;
-
-import java.awt.*;
-import java.io.IOException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.*;
-
-public class RootConfigPanel extends MPanelScaledGUI {
-    private MScrollablePanel navigationScroll;
-
-    private MList navigation = new MList();
-
-    private MScrollablePanel contentScroll;
-
-
-    private final Map<String, MPanel> pages = new HashMap<String, MPanel>();
-    @Getter
-    @Setter
-    private Function<String, MPanel> pageGenerator = ConfigPanelCreator.INSTANCE;
-    @Getter
-    private String currentPage = "";
-
-    private GuiConfigV2 gui;
-
-    private long lastPageSet = System.currentTimeMillis();
-
-    private MTextField search;
-    private MButton guiRelocate;
-
-    private MButton github, discord;
-
-    private final Stack<String> history = new Stack<String>();
-
-    public String getSearchWord() {
-        return search.getText().trim().toLowerCase();
-    }
-
-    public RootConfigPanel(GuiConfigV2 guiConfigV2) {
-        this.gui = guiConfigV2;
-
-        search = new MTextField() {
-            @Override
-            public void edit(String str) {
-                setupNavigation();
-
-                setCurrentPageAndPushHistory("");
-                if (!categoryMap.containsKey(lastOpenCategory)) {
-                    for (Map.Entry<NestedCategory, MPanel> nestedCategoryMPanelEntry : categoryMap.entrySet()) {
-                        if (nestedCategoryMPanelEntry.getValue() instanceof MCategoryElement) {
-                            setCurrentPageAndPushHistory(nestedCategoryMPanelEntry.getKey().categoryFull());
-                            lastOpenCategory = nestedCategoryMPanelEntry.getKey();
-                            break;
-                        }
-                    }
-                }
-                    for (Map.Entry<NestedCategory, MPanel> nestedCategoryMPanelEntry : categoryMap.entrySet()) {
-                        if (nestedCategoryMPanelEntry.getValue() instanceof MCollapsable) {
-                            ((MCollapsable) nestedCategoryMPanelEntry.getValue()).setCollapsed(false);
-                        }
-                    }
-                rePlaceElements();
-            }
-        };
-        search.setPlaceHolder("Search...");
-        add(search);
-        guiRelocate = new MButton();
-        guiRelocate.setText("Edit Gui Locations");
-        guiRelocate.setOnActionPerformed(() -> {
-            Minecraft.getMinecraft().displayGuiScreen(new GuiScreenAdapter(new GlobalHUDScale(new HUDLocationConfig(null))));
-            guiRelocate.setBeingClicked(false);
-        });
-        guiRelocate.setBorder(RenderUtils.blendTwoColors(0xFF141414,0x7702EE67));
-        add(guiRelocate);
-
-        discord = new MButton(); github = new MButton();
-        discord.setText("Discord"); github.setText("Github");
-        discord.setBorder(RenderUtils.blendTwoColors(0xFF141414,0x7702EE67));
-        github.setBorder(RenderUtils.blendTwoColors(0xFF141414,0x7702EE67));
-        github.setOnActionPerformed(() -> {
-            try {
-                Desktop.getDesktop().browse(new URI("https://github.com/Dungeons-Guide/Skyblock-Dungeons-Guide/"));
-            } catch (IOException | URISyntaxException e) {
-                e.printStackTrace();
-            }
-        });
-        discord.setOnActionPerformed(() -> {
-            try {
-                Desktop.getDesktop().browse(new URI("https://discord.gg/VuxayCWGE8"));
-            } catch (IOException | URISyntaxException e) {
-                e.printStackTrace();
-            }
-        });
-        add(discord); add(github);
-
-        navigationScroll = new MScrollablePanel(1);
-        navigationScroll.setHideScrollBarWhenNotNecessary(false);
-
-
-        add(navigationScroll);
-        navigationScroll.add(navigation);
-
-        contentScroll = new MScrollablePanel(3);
-        contentScroll.setHideScrollBarWhenNotNecessary(true);
-        add(contentScroll);
-
-        setupNavigation();
-        navigation.setGap(0);
-        navigation.setDrawLine(false);
-
-        setCurrentPageAndPushHistory("ROOT");
-        rePlaceElements();
-
-        search.setFocused(true);
-    }
-
-
-    private Map<NestedCategory, MPanel> categoryMap = new HashMap<>();
-    private NestedCategory lastOpenCategory;
-    private void setupNavigation() {
-        categoryMap.clear();
-        for (MPanel childComponent : navigation.getChildComponents()) {
-            navigation.remove(childComponent);
-        }
-        NestedCategory root = new NestedCategory("ROOT");
-        Set<String> categoryAllowed = new HashSet<>();
-        String search = this.search.getText().trim().toLowerCase();
-        for (AbstractFeature abstractFeature : FeatureRegistry.getFeatureList()) {
-            if (search.isEmpty()) {
-                categoryAllowed.add("ROOT."+abstractFeature.getCategory()+".");
-            } else if (abstractFeature.getName().toLowerCase().contains(search)) {
-                categoryAllowed.add("ROOT."+abstractFeature.getCategory()+".");
-            } else if (abstractFeature.getDescription().toLowerCase().contains(search)) {
-                categoryAllowed.add("ROOT."+abstractFeature.getCategory()+".");
-            }
-        }
-        for (AbstractFeature abstractFeature : FeatureRegistry.getFeatureList()) {
-            String category = abstractFeature.getCategory();
-            boolean test =false;
-            for (String s : categoryAllowed) {
-                if (s.startsWith("ROOT."+category+".")) {
-                    test = true;
-                    break;
-                }
-            }
-            if (!test) continue;
-
-            NestedCategory currentRoot = root;
-            for (String s : category.split("\\.")) {
-                NestedCategory finalCurrentRoot = currentRoot;
-                if (currentRoot.children().containsKey(s))
-                    currentRoot = currentRoot.children().get(s);
-                else {
-                    currentRoot.child(currentRoot = new NestedCategory(finalCurrentRoot.categoryFull()+"."+s));
-                }
-            }
-
-        }
-
-        for (NestedCategory value : root.children().values()) {
-            setupNavigationRecursive(value, navigation, 0, 17);
-        }
-        ConfigPanelCreator.map.put("ROOT", () -> new MPanelCategory(root, this));
-    }
-    private void setupNavigationRecursive(NestedCategory nestedCategory, MPanel parent, int depth, int offset) {
-        ConfigPanelCreator.map.put(nestedCategory.categoryFull(), () -> new MPanelCategory(nestedCategory, this));
-
-        if (nestedCategory.children().size() == 0) {
-            MCategoryElement current = new MCategoryElement(nestedCategory.categoryFull(),() -> {
-                setCurrentPageAndPushHistory(nestedCategory.categoryFull());
-                lastOpenCategory = nestedCategory;
-            }, 13 * depth + 17, offset, this);
-            parent.add(current);
-            categoryMap.put(nestedCategory, current);
-        } else {
-            MCategoryElement current = new MCategoryElement(nestedCategory.categoryFull(),() -> {
-                setCurrentPageAndPushHistory(nestedCategory.categoryFull());
-                lastOpenCategory = nestedCategory;
-            }, 3,offset, this);
-            MCollapsable mCollapsable = new MCollapsable(current, this::rePlaceElements);
-            mCollapsable.setLeftPad(offset-13);
-            mCollapsable.getLowerElements().setDrawLine(false);
-            mCollapsable.getLowerElements().setGap(0);
-            mCollapsable.setLeftPadElements(0);
-            parent.add(mCollapsable);
-            categoryMap.put(nestedCategory, mCollapsable);
-
-            for (NestedCategory value : nestedCategory.children().values()) {
-                setupNavigationRecursive(value, mCollapsable, depth+1, offset+13);
-            }
-        }
-    }
-
-
-    public void setCurrentPageAndPushHistory(String currentPage) {
-        if (!this.currentPage.equals(currentPage))
-            history.push(this.currentPage);
-        lastOpenCategory = null;
-        this.currentPage = currentPage;
-        setupPage();
-    }
-    public void goBack() {
-        if (history.size() == 0) return;
-        this.currentPage = history.pop();
-        setupPage();
-    }
-
-    private void setupPage() {
-        contentScroll.getContentArea().getChildComponents().forEach(contentScroll.getContentArea()::remove);
-        if (!pages.containsKey(currentPage)) {
-            MPanel page = pageGenerator.apply(currentPage);
-            if (page == null) page = new MNotFound();
-            pages.put(currentPage, page);
-        }
-        contentScroll.getContentArea().add(pages.get(currentPage));
-        rePlaceElements();
-    }
-
-    public void invalidatePage(String page) {
-        pages.remove(page);
-        if (page.equals(currentPage))
-            setupPage();
-    }
-
-    @Override
-    public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) {
-        Dimension effectiveDim = getEffectiveDimension();
-        Gui.drawRect(0,0, (int) (effectiveDim.width),  (int) (effectiveDim.height), RenderUtils.blendAlpha(0x141414, 0.00f));
-        Gui.drawRect(0,0, (int) (effectiveDim.width), 25, RenderUtils.blendAlpha(0x0, 0.20f));
-//        Gui.drawRect(navigationScroll.getBounds().x + navigationScroll.getBounds().width - 10, 25, navigationScroll.getBounds().x + navigationScroll.getBounds().width , 50, RenderUtils.blendAlpha(0xFF141414, 0.04f));
-        Gui.drawRect(0, 25,navigationScroll.getBounds().x + navigationScroll.getBounds().width , 50, RenderUtils.blendAlpha(0xFF141414, 0.08f));
-
-
-        FontRenderer fr  = Minecraft.getMinecraft().fontRendererObj;
-
-        if(AuthManager.getInstance().getToken() == null) {
-            fr.drawString("ERROR CONNECTING TO DG, YOUR COSMETICS ARE NOT VISIBLE",(effectiveDim.width - fr.getStringWidth("ERROR CONNECTING TO DG, YOUR COSMETICS ARE NOT VISIBLE"))/2, (10 - fr.FONT_HEIGHT)/2, 0xFFFF0000);
-        }
-
-        fr.drawString("DungeonsGuide By syeyoung", (effectiveDim.width - fr.getStringWidth("DungeonsGuide By syeyoung"))/2, (25 - fr.FONT_HEIGHT)/2, 0xFF02EE67);
-    }
-
-    @Override
-    public void render0(double parentScale, Point parentPoint, Rectangle parentClip, int absMousex0, int absMousey0, int relMousex0, int relMousey0, float partialTicks) {
-        super.render0(parentScale, parentPoint, parentClip, absMousex0, absMousey0, relMousex0, relMousey0, partialTicks);
-        Dimension effectiveDim = getEffectiveDimension();
-        Gui.drawRect(0,24, (int) (Double.min(1, (System.currentTimeMillis() - lastPageSet)/1000.0) * effectiveDim.width), 25, 0xFF02EE67);
-    }
-
-    @Override
-    public void setBounds(Rectangle bounds) {
-        super.setBounds(bounds);
-        rePlaceElements();
-    }
-
-    @Override
-    public void setScale(double scale) {
-        super.setScale(scale);
-        rePlaceElements();
-    }
-
-    private void rePlaceElements() {
-        Dimension effectiveDim = getEffectiveDimension();
-
-        navigation.setBounds(new Rectangle(new Point(0,1), new Dimension(Math.max(100, Math.max(navigation.getPreferredSize().width, navigationScroll.getBounds().width-10)), navigation.getPreferredSize().height)));
-        navigation.realignChildren();
-
-        navigationScroll.evaluateContentArea();
-        Rectangle navBound;
-        navigationScroll.setBounds(navBound = new Rectangle(0,50, navigation.getBounds().width+10, effectiveDim.height-50));
-        contentScroll.setBounds(new Rectangle(navBound.x + navBound.width, 25, effectiveDim.width - navBound.x - navBound.width, effectiveDim.height-25));
-
-        search.setBounds(new Rectangle(5,30,navBound.x + navBound.width - 10,15));
-
-        guiRelocate.setBounds(new Rectangle(5,5,100,15));
-        github.setBounds(new Rectangle(effectiveDim.width - 80,5,75,15));
-        discord.setBounds(new Rectangle(effectiveDim.width - 160,5,75,15));
-    }
-}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/configv3/FeatureItem.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/configv3/FeatureItem.java
index 5a0c99dc..525d5e97 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/configv3/FeatureItem.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/configv3/FeatureItem.java
@@ -86,6 +86,8 @@ public class FeatureItem extends AnnotatedImportOnlyWidget {
 
     @On(functionName = "configure")
     public void onEdit() {
+        Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F));
+        Navigator.getNavigator(getDomElement()).openPage(feature.getConfigureWidget());
         // do stuff
     }
     @On(functionName = "relocate")
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/configv3/MainPageWidget.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/configv3/MainPageWidget.java
index 8c67ab4c..884ff5d6 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/configv3/MainPageWidget.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/configv3/MainPageWidget.java
@@ -25,6 +25,8 @@ import kr.syeyoung.dungeonsguide.mod.guiv2.xml.AnnotatedImportOnlyWidget;
 import kr.syeyoung.dungeonsguide.mod.guiv2.xml.annotations.Bind;
 import kr.syeyoung.dungeonsguide.mod.guiv2.xml.annotations.On;
 import kr.syeyoung.dungeonsguide.mod.guiv2.xml.data.WidgetList;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.audio.PositionedSoundRecord;
 import net.minecraft.util.ResourceLocation;
 
 import java.awt.*;
@@ -54,6 +56,7 @@ public class MainPageWidget extends AnnotatedImportOnlyWidget {
 
     @On(functionName = "discord")
     public void discord() {
+        Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F));
         try {
             Desktop.getDesktop().browse(new URI("https://discord.gg/VuxayCWGE8"));
         } catch (IOException | URISyntaxException e) {
@@ -63,6 +66,7 @@ public class MainPageWidget extends AnnotatedImportOnlyWidget {
 
     @On(functionName = "github")
     public void github() {
+        Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F));
         try {
             Desktop.getDesktop().browse(new URI("https://github.com/Dungeons-Guide/Skyblock-Dungeons-Guide/"));
         } catch (IOException | URISyntaxException e) {
@@ -71,6 +75,7 @@ public class MainPageWidget extends AnnotatedImportOnlyWidget {
     }
     @On(functionName = "store")
     public void store() {
+        Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F));
         try {
             Desktop.getDesktop().browse(new URI("https://store.dungeons.guide/"));
         } catch (IOException | URISyntaxException e) {
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/configv3/ParameterItem.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/configv3/ParameterItem.java
new file mode 100644
index 00000000..1e6ab18e
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/guiconfig/configv3/ParameterItem.java
@@ -0,0 +1,72 @@
+/*
+ * 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.mod.config.guiconfig.configv3;
+
+import kr.syeyoung.dungeonsguide.mod.config.guiconfig.location2.HUDLocationConfig;
+import kr.syeyoung.dungeonsguide.mod.features.AbstractFeature;
+import kr.syeyoung.dungeonsguide.mod.features.AbstractHUDFeature;
+import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
+import kr.syeyoung.dungeonsguide.mod.guiv2.BindableAttribute;
+import kr.syeyoung.dungeonsguide.mod.guiv2.GuiScreenAdapter;
+import kr.syeyoung.dungeonsguide.mod.guiv2.Widget;
+import kr.syeyoung.dungeonsguide.mod.guiv2.elements.GlobalHUDScale;
+import kr.syeyoung.dungeonsguide.mod.guiv2.xml.AnnotatedImportOnlyWidget;
+import kr.syeyoung.dungeonsguide.mod.guiv2.xml.annotations.Bind;
+import kr.syeyoung.dungeonsguide.mod.guiv2.xml.annotations.On;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.audio.PositionedSoundRecord;
+import net.minecraft.util.ResourceLocation;
+
+public class ParameterItem extends AnnotatedImportOnlyWidget {
+
+    @Bind(variableName = "name")
+    public final BindableAttribute<String> name = new BindableAttribute<>(String.class);
+    @Bind(variableName = "description")
+    public final BindableAttribute<String> description = new BindableAttribute<>(String.class);
+
+    @Bind(variableName = "iconVisibility")
+    public final BindableAttribute<String> iconVisibility = new BindableAttribute<>(String.class, "show");
+    @Bind(variableName = "icon")
+    public final BindableAttribute<String> icon = new BindableAttribute<>(String.class, "dungeonsguide:textures/darklogo.png");
+    @Bind(variableName = "edit")
+    public final BindableAttribute<Widget> edit = new BindableAttribute<>(Widget.class);
+
+
+
+    private FeatureParameter featureParameter;
+    public ParameterItem(FeatureParameter featureParameter, Widget childEditor) {
+        super(new ResourceLocation("dungeonsguide:gui/config/parameteritem.gui"));
+        this.featureParameter = featureParameter;
+        update();
+
+
+        if (featureParameter.getIcon() != null) {
+            icon.setValue(featureParameter.getIcon());
+            iconVisibility.setValue("show");
+        }
+        edit.setValue(childEditor);
+    }
+
+    public void update() {
+        this.name.setValue(featureParameter.getName());
+        this.description.setValue(featureParameter.getDescription());
+    }
+
+
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/AColor.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/AColor.java
index ecb0e838..35b9e41f 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/AColor.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/AColor.java
@@ -18,6 +18,7 @@
 
 package kr.syeyoung.dungeonsguide.mod.config.types;
 
+import lombok.EqualsAndHashCode;
 import lombok.Getter;
 import lombok.Setter;
 
@@ -25,6 +26,7 @@ import java.awt.*;
 
 @Getter
 @Setter
+@EqualsAndHashCode(callSuper = true)
 public class AColor extends Color {
     private boolean chroma;
     private float chromaSpeed;
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/FeatureTypeHandler.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/FeatureTypeHandler.java
new file mode 100644
index 00000000..dab487a4
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/FeatureTypeHandler.java
@@ -0,0 +1,32 @@
+/*
+ *     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.mod.config.types;
+
+import com.google.gson.JsonElement;
+import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
+import kr.syeyoung.dungeonsguide.mod.guiv2.Widget;
+
+public interface FeatureTypeHandler<T> {
+    T deserialize(JsonElement element);
+    JsonElement serialize(T element);
+
+    default Widget createDefaultWidgetFor(FeatureParameter parameter) {
+        return null;
+    }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCAColor.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCAColor.java
index 7f6f4b93..4c95d4d9 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCAColor.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCAColor.java
@@ -21,13 +21,27 @@ package kr.syeyoung.dungeonsguide.mod.config.types;
 import com.google.gson.JsonElement;
 import com.google.gson.JsonObject;
 import com.google.gson.JsonPrimitive;
+import kr.syeyoung.dungeonsguide.mod.config.guiconfig.configv3.ParameterItem;
+import kr.syeyoung.dungeonsguide.mod.config.types.coloredit.ColorEditPopup;
+import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
+import kr.syeyoung.dungeonsguide.mod.guiv2.BindableAttribute;
+import kr.syeyoung.dungeonsguide.mod.guiv2.DomElement;
+import kr.syeyoung.dungeonsguide.mod.guiv2.Widget;
+import kr.syeyoung.dungeonsguide.mod.guiv2.elements.popups.AbsLocationPopup;
+import kr.syeyoung.dungeonsguide.mod.guiv2.elements.popups.PopupMgr;
+import kr.syeyoung.dungeonsguide.mod.guiv2.layouter.Layouter;
+import kr.syeyoung.dungeonsguide.mod.guiv2.primitive.Rect;
+import kr.syeyoung.dungeonsguide.mod.guiv2.renderer.Renderer;
+import kr.syeyoung.dungeonsguide.mod.guiv2.renderer.RenderingContext;
+import kr.syeyoung.dungeonsguide.mod.guiv2.xml.AnnotatedImportOnlyWidget;
+import kr.syeyoung.dungeonsguide.mod.guiv2.xml.annotations.Bind;
+import kr.syeyoung.dungeonsguide.mod.guiv2.xml.annotations.On;
+import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.util.ResourceLocation;
 
-public class TCAColor implements TypeConverter<AColor> {
-    @Override
-    public String getTypeString() {
-        return "acolor";
-    }
-
+public class TCAColor implements FeatureTypeHandler<AColor> {
+    public static final TCAColor INSTANCE = new TCAColor();
     @Override
     public AColor deserialize(JsonElement element) {
         if (element instanceof JsonPrimitive)
@@ -48,4 +62,87 @@ public class TCAColor implements TypeConverter<AColor> {
         object.addProperty("chromaSpeed", element.getChromaSpeed());
         return object;
     }
+
+
+    @Override
+    public Widget createDefaultWidgetFor(FeatureParameter parameter) {
+        ParameterItem parameterItem = new ParameterItem(parameter, new ColorEditWidget(parameter));
+        return parameterItem;
+    }
+
+    public static class ColorEditWidget extends AnnotatedImportOnlyWidget implements Renderer {
+        @Bind(variableName = "color")
+        public final BindableAttribute<Integer> color = new BindableAttribute<>(Integer.class);
+        @Bind(variableName = "hover")
+        public final BindableAttribute<Integer> hover = new BindableAttribute<>(Integer.class);
+        @Bind(variableName = "click")
+        public final BindableAttribute<Integer> click = new BindableAttribute<>(Integer.class);
+
+        public final BindableAttribute<AColor> aColorBindableAttribute = new BindableAttribute<>(AColor.class);
+
+        private FeatureParameter<AColor> featureParameter;
+        public ColorEditWidget(FeatureParameter<AColor> featureParameter) {
+            super(new ResourceLocation("dungeonsguide:gui/config/parameter/color.gui"));
+            this.featureParameter = featureParameter;
+
+            aColorBindableAttribute.addOnUpdate((old, color) -> {
+                this.featureParameter.setValue(color);
+            });
+            aColorBindableAttribute.setValue(featureParameter.getValue());
+        }
+
+        private AbsLocationPopup locationPopup;
+        @On(functionName = "setColor")
+        public void openDialog() {
+            if (locationPopup != null) return;
+            PopupMgr popupMgr = PopupMgr.getPopupMgr(getDomElement());
+            ColorEditPopup colorEditPopup = new ColorEditPopup(aColorBindableAttribute);
+            double x = getDomElement().getAbsBounds().getX();
+            double y = getDomElement().getAbsBounds().getY()+getDomElement().getAbsBounds().getHeight();
+            locationPopup =
+                    new AbsLocationPopup(x,y, colorEditPopup,true);
+            popupMgr.openPopup(locationPopup, (cb) -> {
+                locationPopup = null;
+            });
+        }
+
+        @Override
+        public void onUnmount() {
+            super.onUnmount();
+            if (locationPopup != null)
+                PopupMgr.getPopupMgr(getDomElement()).closePopup(locationPopup);
+        }
+
+        @Override
+        public void doRender(int absMouseX, int absMouseY, double relMouseX, double relMouseY, float partialTicks, RenderingContext context, DomElement buildContext) {
+            int color = RenderUtils.getColorAt(getDomElement().getAbsBounds().getX(), getDomElement().getAbsBounds().getY(), aColorBindableAttribute.getValue());
+
+            this.color.setValue(color);
+            this.hover.setValue(RenderUtils.blendAlpha(color, 0.2f));
+            this.click.setValue(RenderUtils.blendAlpha(color, 0.4f));
+
+            if (buildContext.getChildren().isEmpty()) return;
+            DomElement value = buildContext.getChildren().get(0);
+
+            Rect original = value.getRelativeBound();
+            if (original == null) return;
+            GlStateManager.translate(original.getX(), original.getY(), 0);
+
+            double absXScale = buildContext.getAbsBounds().getWidth() / buildContext.getSize().getWidth();
+            double absYScale = buildContext.getAbsBounds().getHeight() / buildContext.getSize().getHeight();
+
+            Rect elementABSBound = new Rect(
+                    (buildContext.getAbsBounds().getX() + original.getX() * absXScale),
+                    (buildContext.getAbsBounds().getY() + original.getY() * absYScale),
+                    (original.getWidth() * absXScale),
+                    (original.getHeight() * absYScale)
+            );
+            value.setAbsBounds(elementABSBound);
+
+            value.getRenderer().doRender(absMouseX, absMouseY,
+                    relMouseX - original.getX(),
+                    relMouseY - original.getY(), partialTicks, context, value);
+        }
+    }
+
 }
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCBoolean.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCBoolean.java
index f973f495..904b8e4b 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCBoolean.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCBoolean.java
@@ -20,12 +20,19 @@ package kr.syeyoung.dungeonsguide.mod.config.types;
 
 import com.google.gson.JsonElement;
 import com.google.gson.JsonPrimitive;
+import kr.syeyoung.dungeonsguide.mod.config.guiconfig.configv3.ParameterItem;
+import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
+import kr.syeyoung.dungeonsguide.mod.guiv2.BindableAttribute;
+import kr.syeyoung.dungeonsguide.mod.guiv2.Widget;
+import kr.syeyoung.dungeonsguide.mod.guiv2.xml.AnnotatedImportOnlyWidget;
+import kr.syeyoung.dungeonsguide.mod.guiv2.xml.DomElementRegistry;
+import kr.syeyoung.dungeonsguide.mod.guiv2.xml.annotations.Bind;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.audio.PositionedSoundRecord;
+import net.minecraft.util.ResourceLocation;
 
-public class TCBoolean implements TypeConverter<Boolean> {
-    @Override
-    public String getTypeString() {
-        return "boolean";
-    }
+public class TCBoolean implements FeatureTypeHandler<Boolean> {
+    public static final TCBoolean INSTANCE = new TCBoolean();
 
     @Override
     public Boolean deserialize(JsonElement element) {
@@ -36,4 +43,23 @@ public class TCBoolean implements TypeConverter<Boolean> {
     public JsonElement serialize(Boolean element) {
         return new JsonPrimitive(element);
     }
+
+    @Override
+    public Widget createDefaultWidgetFor(FeatureParameter parameter) {
+        ParameterItem parameterItem = new ParameterItem(parameter, new BooleanEditWidget(parameter));
+        return parameterItem;
+    }
+
+    public static class BooleanEditWidget extends AnnotatedImportOnlyWidget {
+        @Bind(variableName = "enabled")
+        public final BindableAttribute<Boolean> isEnabled = new BindableAttribute<>(Boolean.class);
+        public BooleanEditWidget(FeatureParameter<Boolean> featureParameter) {
+            super(new ResourceLocation("dungeonsguide:gui/config/parameter/boolean.gui"));
+            isEnabled.setValue(featureParameter.getValue());
+            isEnabled.addOnUpdate((old,neu) -> {
+                Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F));
+                featureParameter.setValue(neu);
+            });
+        }
+    }
 }
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCColor.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCColor.java
deleted file mode 100644
index 2544a4f3..00000000
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCColor.java
+++ /dev/null
@@ -1,41 +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.mod.config.types;
-
-import com.google.gson.JsonElement;
-import com.google.gson.JsonPrimitive;
-
-import java.awt.*;
-
-public class TCColor implements TypeConverter<Color> {
-    @Override
-    public String getTypeString() {
-        return "color";
-    }
-
-    @Override
-    public Color deserialize(JsonElement element) {
-        return new Color(element.getAsInt());
-    }
-
-    @Override
-    public JsonElement serialize(Color element) {
-        return new JsonPrimitive(element.getRGB());
-    }
-}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCEnum.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCEnum.java
new file mode 100644
index 00000000..325f3688
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCEnum.java
@@ -0,0 +1,104 @@
+/*
+ *     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.mod.config.types;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonPrimitive;
+import kr.syeyoung.dungeonsguide.mod.config.guiconfig.configv3.ParameterItem;
+import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
+import kr.syeyoung.dungeonsguide.mod.guiv2.BindableAttribute;
+import kr.syeyoung.dungeonsguide.mod.guiv2.DomElement;
+import kr.syeyoung.dungeonsguide.mod.guiv2.ElementTreeWalkIterator;
+import kr.syeyoung.dungeonsguide.mod.guiv2.Widget;
+import kr.syeyoung.dungeonsguide.mod.guiv2.xml.AnnotatedImportOnlyWidget;
+import kr.syeyoung.dungeonsguide.mod.guiv2.xml.annotations.Bind;
+import kr.syeyoung.dungeonsguide.mod.guiv2.xml.annotations.On;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.audio.PositionedSoundRecord;
+import net.minecraft.util.ResourceLocation;
+import org.lwjgl.input.Keyboard;
+
+public class TCEnum<T extends Enum<T>> implements FeatureTypeHandler<T> {
+    private final T[] values;
+    public TCEnum(T[] values) {
+        this.values = values;
+    }
+
+    @Override
+    public T deserialize(JsonElement element) {
+        for (T value : values) {
+            if (element.getAsString().equalsIgnoreCase(value.name())) return value;
+        }
+        return values[0];
+    }
+
+    @Override
+    public JsonElement serialize(T element) {
+        return new JsonPrimitive(element.name());
+    }
+
+
+    @Override
+    public Widget createDefaultWidgetFor(FeatureParameter parameter) {
+        ParameterItem parameterItem = new ParameterItem(parameter, new EnumEditWidget(values, parameter));
+        return parameterItem;
+    }
+
+    public static class EnumEditWidget<T extends Enum<T>> extends AnnotatedImportOnlyWidget {
+        @Bind(variableName = "value")
+        public final BindableAttribute<String> value = new BindableAttribute<>(String.class);
+        private T[] values;
+        private int idx;
+        private FeatureParameter<T> featureParameter;
+        public EnumEditWidget(T[] values, FeatureParameter<T> featureParameter) {
+            super(new ResourceLocation("dungeonsguide:gui/config/parameter/stringChoice.gui"));
+            this.idx = featureParameter.getValue().ordinal();
+            this.values = values;
+            this.featureParameter = featureParameter;
+            value.setValue(featureParameter.getValue().name());
+        }
+
+        @On(functionName = "inc")
+        public void inc() {
+            Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F));
+            idx = (idx + 1) % values.length;
+            value.setValue(values[idx].name());
+            featureParameter.setValue(values[idx]);
+            for (DomElement dom : new ElementTreeWalkIterator(getDomElement())) {
+                if (dom.getWidget() instanceof ParameterItem) {
+                    ((ParameterItem) dom.getWidget()).update();
+                    break;
+                }
+            }
+        }
+        @On(functionName = "dec")
+        public void dec() {
+            Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F));
+            idx = (values.length + idx - 1) % values.length;
+            value.setValue(values[idx].name());
+            featureParameter.setValue(values[idx]);
+            for (DomElement dom : new ElementTreeWalkIterator(getDomElement())) {
+                if (dom.getWidget() instanceof ParameterItem) {
+                    ((ParameterItem) dom.getWidget()).update();
+                    break;
+                }
+            }
+        }
+    }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCFloat.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCFloat.java
index 2f2aa72f..5bd47d09 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCFloat.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCFloat.java
@@ -20,13 +20,20 @@ package kr.syeyoung.dungeonsguide.mod.config.types;
 
 import com.google.gson.JsonElement;
 import com.google.gson.JsonPrimitive;
+import kr.syeyoung.dungeonsguide.mod.config.guiconfig.configv3.ParameterItem;
+import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
+import kr.syeyoung.dungeonsguide.mod.guiv2.BindableAttribute;
+import kr.syeyoung.dungeonsguide.mod.guiv2.Widget;
+import kr.syeyoung.dungeonsguide.mod.guiv2.xml.AnnotatedImportOnlyWidget;
+import kr.syeyoung.dungeonsguide.mod.guiv2.xml.annotations.Bind;
+import kr.syeyoung.dungeonsguide.mod.guiv2.xml.annotations.On;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.audio.PositionedSoundRecord;
+import net.minecraft.util.ResourceLocation;
+import org.lwjgl.input.Keyboard;
 
-public class TCFloat implements TypeConverter<Float> {
-    @Override
-    public String getTypeString() {
-        return "float";
-    }
-
+public class TCFloat implements FeatureTypeHandler<Float> {
+    public static final TCFloat INSTANCE = new TCFloat();
     @Override
     public Float deserialize(JsonElement element) {
         return element.getAsFloat();
@@ -36,4 +43,44 @@ public class TCFloat implements TypeConverter<Float> {
     public JsonElement serialize(Float element) {
         return new JsonPrimitive(element);
     }
+
+
+    @Override
+    public Widget createDefaultWidgetFor(FeatureParameter parameter) {
+        ParameterItem parameterItem = new ParameterItem(parameter, new FloatEditWidget(parameter));
+        return parameterItem;
+    }
+
+    public static class FloatEditWidget extends AnnotatedImportOnlyWidget {
+        @Bind(variableName = "value")
+        public final BindableAttribute<String> value = new BindableAttribute<>(String.class);
+        private float truth;
+
+        public FloatEditWidget(FeatureParameter<Float> featureParameter) {
+            super(new ResourceLocation("dungeonsguide:gui/config/parameter/number.gui"));
+            this.truth = featureParameter.getValue();
+            value.setValue(String.valueOf(truth));
+            value.addOnUpdate((old, neu) -> {
+                try {
+                    truth = Float.parseFloat(neu);
+                    featureParameter.setValue(truth);
+                } catch (Exception e) {
+                }
+            });
+        }
+
+        @On(functionName = "inc")
+        public void inc() {
+            Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F));
+            truth += (Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) ? 1 : 0.1);
+            value.setValue(String.valueOf(truth));
+        }
+
+        @On(functionName = "dec")
+        public void dec() {
+            Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F));
+            truth -= (Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) ? 1 : 0.1);
+            value.setValue(String.valueOf(truth));
+        }
+    }
 }
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCGUIPosition.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCGUIPosition.java
index dc2f70fa..d40418ea 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCGUIPosition.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCGUIPosition.java
@@ -21,11 +21,8 @@ package kr.syeyoung.dungeonsguide.mod.config.types;
 import com.google.gson.JsonElement;
 import com.google.gson.JsonObject;
 
-public class TCGUIPosition implements TypeConverter<GUIPosition> {
-    @Override
-    public String getTypeString() {
-        return "guipos";
-    }
+public class TCGUIPosition implements FeatureTypeHandler<GUIPosition> {
+    public static final TCGUIPosition INSTANCE = new TCGUIPosition();
 
     @Override
     public GUIPosition deserialize(JsonElement element) {
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCInteger.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCInteger.java
index e895345d..37a5e840 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCInteger.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCInteger.java
@@ -20,12 +20,20 @@ package kr.syeyoung.dungeonsguide.mod.config.types;
 
 import com.google.gson.JsonElement;
 import com.google.gson.JsonPrimitive;
+import kr.syeyoung.dungeonsguide.mod.config.guiconfig.configv3.ParameterItem;
+import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
+import kr.syeyoung.dungeonsguide.mod.guiv2.BindableAttribute;
+import kr.syeyoung.dungeonsguide.mod.guiv2.Widget;
+import kr.syeyoung.dungeonsguide.mod.guiv2.xml.AnnotatedImportOnlyWidget;
+import kr.syeyoung.dungeonsguide.mod.guiv2.xml.annotations.Bind;
+import kr.syeyoung.dungeonsguide.mod.guiv2.xml.annotations.On;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.audio.PositionedSoundRecord;
+import net.minecraft.util.ResourceLocation;
+import org.lwjgl.input.Keyboard;
 
-public class TCInteger implements TypeConverter<Integer> {
-    @Override
-    public String getTypeString() {
-        return "integer";
-    }
+public class TCInteger implements FeatureTypeHandler<Integer> {
+    public static final TCInteger INSTANCE = new TCInteger();
 
     @Override
     public Integer deserialize(JsonElement element) {
@@ -36,4 +44,41 @@ public class TCInteger implements TypeConverter<Integer> {
     public JsonElement serialize(Integer element) {
         return new JsonPrimitive(element);
     }
+
+
+    @Override
+    public Widget createDefaultWidgetFor(FeatureParameter parameter) {
+        ParameterItem parameterItem = new ParameterItem(parameter, new IntegerEditWidget(parameter));
+        return parameterItem;
+    }
+
+    public static class IntegerEditWidget extends AnnotatedImportOnlyWidget {
+        @Bind(variableName = "value")
+        public final BindableAttribute<String> value = new BindableAttribute<>(String.class);
+        private int truth;
+        public IntegerEditWidget(FeatureParameter<Integer> featureParameter) {
+            super(new ResourceLocation("dungeonsguide:gui/config/parameter/number.gui"));
+            this.truth = featureParameter.getValue();
+            value.setValue(String.valueOf(truth));
+            value.addOnUpdate((old,neu) -> {
+                try {
+                    truth = Integer.parseInt(neu);
+                    featureParameter.setValue(truth);
+                } catch (Exception e) {}
+            });
+        }
+
+        @On(functionName = "inc")
+        public void inc() {
+            Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F));
+            truth +=(Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) ? 5 : 1);
+            value.setValue(String.valueOf(truth));
+        }
+        @On(functionName = "dec")
+        public void dec() {
+            Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F));
+            truth -=(Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) ? 5 : 1);
+            value.setValue(String.valueOf(truth));
+        }
+    }
 }
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCKeybind.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCKeybind.java
index 5b3bb09b..f817d3f2 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCKeybind.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCKeybind.java
@@ -20,13 +20,20 @@ package kr.syeyoung.dungeonsguide.mod.config.types;
 
 import com.google.gson.JsonElement;
 import com.google.gson.JsonPrimitive;
+import kr.syeyoung.dungeonsguide.mod.config.guiconfig.configv3.ParameterItem;
+import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
+import kr.syeyoung.dungeonsguide.mod.guiv2.BindableAttribute;
+import kr.syeyoung.dungeonsguide.mod.guiv2.Widget;
+import kr.syeyoung.dungeonsguide.mod.guiv2.xml.AnnotatedImportOnlyWidget;
+import kr.syeyoung.dungeonsguide.mod.guiv2.xml.annotations.Bind;
+import kr.syeyoung.dungeonsguide.mod.guiv2.xml.annotations.On;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.audio.PositionedSoundRecord;
+import net.minecraft.client.settings.GameSettings;
+import net.minecraft.util.ResourceLocation;
 
-public class TCKeybind implements TypeConverter<Integer> {
-    @Override
-    public String getTypeString() {
-        return "keybind";
-    }
-
+public class TCKeybind implements FeatureTypeHandler<Integer> {
+    public static final TCKeybind INSTANCE = new TCKeybind();
     @Override
     public Integer deserialize(JsonElement element) {
         return element.getAsInt();
@@ -36,4 +43,49 @@ public class TCKeybind implements TypeConverter<Integer> {
     public JsonElement serialize(Integer element) {
         return new JsonPrimitive(element);
     }
+
+
+    @Override
+    public Widget createDefaultWidgetFor(FeatureParameter parameter) {
+        ParameterItem parameterItem = new ParameterItem(parameter, new KeybindEditWidget(parameter));
+        return parameterItem;
+    }
+
+    public static class KeybindEditWidget extends AnnotatedImportOnlyWidget {
+        @Bind(variableName = "key")
+        public final BindableAttribute<String> value = new BindableAttribute<>(String.class);
+
+        private int currentKey = 0;
+        private boolean listen = false;
+        private FeatureParameter<Integer> parameter;
+        public KeybindEditWidget(FeatureParameter<Integer> featureParameter) {
+            super(new ResourceLocation("dungeonsguide:gui/config/parameter/keybind.gui"));
+            this.parameter = featureParameter;
+            currentKey = featureParameter.getValue();
+            value.setValue(GameSettings.getKeyDisplayString(currentKey));
+        }
+
+        @On(functionName = "setKey")
+        public void listen() {
+            Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F));
+            getDomElement().obtainFocus();
+            value.setValue("> "+GameSettings.getKeyDisplayString(currentKey)+" <");
+            listen =true;
+        }
+
+        @Override
+        public void keyPressed(char typedChar, int keyCode) {
+            if (!listen) return;
+            if (keyCode == 1) {
+                currentKey = 0;
+            } else if (keyCode != 0) {
+                currentKey = keyCode;
+            } else if (typedChar > 0) {
+                currentKey = typedChar + 256;
+            }
+            listen = false;
+            parameter.setValue(currentKey);
+            value.setValue(GameSettings.getKeyDisplayString(currentKey));
+        }
+    }
 }
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCRectangle.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCRectangle.java
index 46d7de16..8ce9299b 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCRectangle.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCRectangle.java
@@ -23,11 +23,8 @@ import com.google.gson.JsonObject;
 
 import java.awt.*;
 
-public class TCRectangle implements TypeConverter<Rectangle> {
-    @Override
-    public String getTypeString() {
-        return "rect";
-    }
+public class TCRectangle implements FeatureTypeHandler<Rectangle> {
+    public static final TCRectangle INSTANCE = new TCRectangle();
 
     @Override
     public Rectangle deserialize(JsonElement element) {
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCString.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCString.java
index b2f9dab4..369db398 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCString.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCString.java
@@ -20,12 +20,16 @@ package kr.syeyoung.dungeonsguide.mod.config.types;
 
 import com.google.gson.JsonElement;
 import com.google.gson.JsonPrimitive;
+import kr.syeyoung.dungeonsguide.mod.config.guiconfig.configv3.ParameterItem;
+import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
+import kr.syeyoung.dungeonsguide.mod.guiv2.BindableAttribute;
+import kr.syeyoung.dungeonsguide.mod.guiv2.Widget;
+import kr.syeyoung.dungeonsguide.mod.guiv2.xml.AnnotatedImportOnlyWidget;
+import kr.syeyoung.dungeonsguide.mod.guiv2.xml.annotations.Bind;
+import net.minecraft.util.ResourceLocation;
 
-public class TCString implements TypeConverter<String> {
-    @Override
-    public String getTypeString() {
-        return "string";
-    }
+public class TCString implements FeatureTypeHandler<String> {
+    public static final TCString INSTANCE = new TCString();
 
     @Override
     public String deserialize(JsonElement element) {
@@ -36,4 +40,21 @@ public class TCString implements TypeConverter<String> {
     public JsonElement serialize(String element) {
         return new JsonPrimitive(element);
     }
+
+
+    @Override
+    public Widget createDefaultWidgetFor(FeatureParameter parameter) {
+        ParameterItem parameterItem = new ParameterItem(parameter, new StringEditWidget(parameter));
+        return parameterItem;
+    }
+
+    public static class StringEditWidget extends AnnotatedImportOnlyWidget {
+        @Bind(variableName = "value")
+        public final BindableAttribute<String> value = new BindableAttribute<>(String.class);
+        public StringEditWidget(FeatureParameter<String> featureParameter) {
+            super(new ResourceLocation("dungeonsguide:gui/config/parameter/string.gui"));
+            value.setValue(featureParameter.getValue());
+            value.addOnUpdate((old,neu) -> featureParameter.setValue(neu));
+        }
+    }
 }
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCStringList.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCStringList.java
index 24327cfa..53505009 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCStringList.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCStringList.java
@@ -25,11 +25,8 @@ import com.google.gson.JsonPrimitive;
 import java.util.ArrayList;
 import java.util.List;
 
-public class TCStringList implements TypeConverter<List<String>> {
-    @Override
-    public String getTypeString() {
-        return "stringlist";
-    }
+public class TCStringList implements FeatureTypeHandler<List<String>> {
+    public static final TCStringList INSTANCE = new TCStringList();
 
     @Override
     public List<String> deserialize(JsonElement element) {
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCTextStyle.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCTextStyle.java
index a2b1c374..9b6bcbb5 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCTextStyle.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCTextStyle.java
@@ -23,17 +23,14 @@ import com.google.gson.JsonObject;
 import kr.syeyoung.dungeonsguide.mod.features.text.TextStyle;
 
 
-public class TCTextStyle implements TypeConverter<TextStyle> {
-    @Override
-    public String getTypeString() {
-        return "textstyle";
-    }
+public class TCTextStyle implements FeatureTypeHandler<TextStyle> {
+    public static final TCTextStyle INSTANCE = new TCTextStyle();
 
     @Override
     public TextStyle deserialize(JsonElement element) {
         TextStyle textStyle = new TextStyle();
-        textStyle.setColor(TypeConverterRegistry.getTypeConverter("acolor", AColor.class).deserialize(element.getAsJsonObject().get("color")));
-        textStyle.setBackground(element.getAsJsonObject().has("background") ? TypeConverterRegistry.getTypeConverter("acolor", AColor.class).deserialize(element.getAsJsonObject().get("background"))
+        textStyle.setColor(TCAColor.INSTANCE.deserialize(element.getAsJsonObject().get("color")));
+        textStyle.setBackground(element.getAsJsonObject().has("background") ? TCAColor.INSTANCE.deserialize(element.getAsJsonObject().get("background"))
                 : new AColor(0x00777777, true));
         textStyle.setGroupName(element.getAsJsonObject().get("group").getAsString());
         if (element.getAsJsonObject().has("shadow"))
@@ -44,8 +41,8 @@ public class TCTextStyle implements TypeConverter<TextStyle> {
     @Override
     public JsonElement serialize(TextStyle element) {
         JsonObject jsonObject = new JsonObject();
-        jsonObject.add("color", TypeConverterRegistry.getTypeConverter("acolor", AColor.class).serialize(element.getColor()));
-        jsonObject.add("background", TypeConverterRegistry.getTypeConverter("acolor", AColor.class).serialize(element.getBackground()));
+        jsonObject.add("color", TCAColor.INSTANCE.serialize(element.getColor()));
+        jsonObject.add("background", TCAColor.INSTANCE.serialize(element.getBackground()));
         jsonObject.addProperty("group", element.getGroupName());
         jsonObject.addProperty("shadow", element.isShadow());
         return jsonObject;
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCTextStyleList.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCTextStyleList.java
index accbc01d..97685c2f 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCTextStyleList.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TCTextStyleList.java
@@ -25,16 +25,13 @@ import kr.syeyoung.dungeonsguide.mod.features.text.TextStyle;
 import java.util.ArrayList;
 import java.util.List;
 
-public class TCTextStyleList implements TypeConverter<List<TextStyle>> {
-    @Override
-    public String getTypeString() {
-        return "list_textStyle";
-    }
+public class TCTextStyleList implements FeatureTypeHandler<List<TextStyle>> {
+    public static final TCTextStyleList INSTANCE = new TCTextStyleList();
 
     @Override
     public List<TextStyle>  deserialize(JsonElement element) {
         JsonArray arr = element.getAsJsonArray();
-        TypeConverter<TextStyle> conv = TypeConverterRegistry.getTypeConverter("textstyle", TextStyle.class);
+        FeatureTypeHandler<TextStyle> conv = TCTextStyle.INSTANCE;
         List<TextStyle> texts = new ArrayList<TextStyle>();
         for (JsonElement element2:arr) {
             texts.add(conv.deserialize(element2));
@@ -45,7 +42,7 @@ public class TCTextStyleList implements TypeConverter<List<TextStyle>> {
     @Override
     public JsonElement serialize(List<TextStyle> element) {
         JsonArray array = new JsonArray();
-        TypeConverter<TextStyle> conv = TypeConverterRegistry.getTypeConverter("textstyle", TextStyle.class);
+        FeatureTypeHandler<TextStyle> conv = TCTextStyle.INSTANCE;
         for (TextStyle st:element) {
             array.add(conv.serialize(st));
         }
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TypeConverter.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TypeConverter.java
deleted file mode 100644
index eb4c7a27..00000000
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TypeConverter.java
+++ /dev/null
@@ -1,29 +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.mod.config.types;
-
-import com.google.gson.JsonElement;
-
-public interface TypeConverter<T> {
-    String getTypeString();
-
-    T deserialize(JsonElement element);
-
-    JsonElement serialize(T element);
-}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TypeConverterRegistry.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TypeConverterRegistry.java
index d8dfd5e0..6eb9fa5a 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TypeConverterRegistry.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/TypeConverterRegistry.java
@@ -1,6 +1,6 @@
 /*
  * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
- * Copyright (C) 2021  cyoung06
+ * 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,35 +18,5 @@
 
 package kr.syeyoung.dungeonsguide.mod.config.types;
 
-import java.util.HashMap;
-import java.util.Map;
-
 public class TypeConverterRegistry {
-    private static final Map<String, TypeConverter> typeConverterMap = new HashMap<String, TypeConverter>();
-
-    public static void register(TypeConverter typeConverter) {
-        typeConverterMap.put(typeConverter.getTypeString(), typeConverter);
-    }
-
-    public static TypeConverter getTypeConverter(String type_string) {
-        return typeConverterMap.get(type_string);
-    }
-    public static <T> TypeConverter<T> getTypeConverter(String type_string, Class<T> t) {
-        return (TypeConverter<T>)typeConverterMap.get(type_string);
-    }
-
-    static {
-        register(new TCBoolean());
-        register(new TCInteger());
-        register(new TCRectangle());
-        register(new TCGUIPosition());
-        register(new TCString());
-        register(new TCColor());
-        register(new TCFloat());
-        register(new TCAColor());
-        register(new TCTextStyleList());
-        register(new TCTextStyle());
-        register(new TCStringList());
-        register(new TCKeybind());
-    }
 }
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/coloredit/AlphaBar.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/coloredit/AlphaBar.java
new file mode 100644
index 00000000..5e01d079
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/coloredit/AlphaBar.java
@@ -0,0 +1,138 @@
+/*
+ * 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.mod.config.types.coloredit;
+
+import kr.syeyoung.dungeonsguide.mod.config.types.AColor;
+import kr.syeyoung.dungeonsguide.mod.guiv2.BindableAttribute;
+import kr.syeyoung.dungeonsguide.mod.guiv2.DomElement;
+import kr.syeyoung.dungeonsguide.mod.guiv2.Widget;
+import kr.syeyoung.dungeonsguide.mod.guiv2.layouter.Layouter;
+import kr.syeyoung.dungeonsguide.mod.guiv2.primitive.ConstraintBox;
+import kr.syeyoung.dungeonsguide.mod.guiv2.primitive.Size;
+import kr.syeyoung.dungeonsguide.mod.guiv2.renderer.Renderer;
+import kr.syeyoung.dungeonsguide.mod.guiv2.renderer.RenderingContext;
+import kr.syeyoung.dungeonsguide.mod.shader.ShaderManager;
+import kr.syeyoung.dungeonsguide.mod.shader.ShaderProgram;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.client.renderer.Tessellator;
+import net.minecraft.client.renderer.WorldRenderer;
+import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
+import org.lwjgl.opengl.GL20;
+
+import java.awt.*;
+import java.util.Collections;
+import java.util.List;
+
+public class AlphaBar extends Widget implements Renderer, Layouter {
+    public final BindableAttribute<AColor> color = new BindableAttribute<>(AColor.class);
+    public AlphaBar(BindableAttribute<AColor> aColorBindableAttribute) {
+        aColorBindableAttribute.exportTo(color);
+    }
+
+    @Override
+    public List<Widget> build(DomElement buildContext) {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public Size layout(DomElement buildContext, ConstraintBox constraintBox) {
+        return new Size(constraintBox.getMaxWidth(), constraintBox.getMaxHeight());
+    }
+
+    @Override
+    public void doRender(int absMouseX, int absMouseY, double relMouseX, double relMouseY, float partialTicks, RenderingContext context, DomElement buildContext) {
+        ShaderProgram shaderProgram = ShaderManager.getShader("shaders/roundrect");
+        shaderProgram.useShader();
+        shaderProgram.uploadUniform("radius", (float)(5.0f * buildContext.getAbsBounds().getWidth() / buildContext.getSize().getWidth()));
+        shaderProgram.uploadUniform("halfSize", (float) buildContext.getAbsBounds().getWidth()/2, (float) buildContext.getAbsBounds().getHeight()/2);
+        shaderProgram.uploadUniform("centerPos",
+                (float) (buildContext.getAbsBounds().getX()+buildContext.getAbsBounds().getWidth()/2),
+                Minecraft.getMinecraft().displayHeight - (float) (buildContext.getAbsBounds().getY() + buildContext.getAbsBounds().getHeight()/2));
+        shaderProgram.uploadUniform("smoothness", 0.0f);
+
+        Tessellator tessellator = Tessellator.getInstance();
+        WorldRenderer worldRenderer = tessellator.getWorldRenderer();
+        GlStateManager.enableBlend();
+        GlStateManager.disableTexture2D();
+        GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0);
+        double width = buildContext.getSize().getWidth();
+        double height = buildContext.getSize().getHeight();
+        worldRenderer.begin(7, DefaultVertexFormats.POSITION_COLOR);
+
+        int r,g,b;
+        int color = this.color.getValue().getRGB();
+        r = ((color >> 16) &0xFF);
+        g = ((color >> 8) &0xFF) ;
+        b= ((color) &0xFF);
+        worldRenderer.pos(0, height, 0.0).color(r,g,b,0).endVertex();
+        worldRenderer.pos(width, height, 0.0).color(r,g,b,0).endVertex();
+        worldRenderer.pos(width, 0, 0.0).color(r,g,b,255).endVertex();
+        worldRenderer.pos(0, 0, 0.0).color(r,g,b,255).endVertex();
+        tessellator.draw();
+        GlStateManager.enableTexture2D();
+
+        GL20.glUseProgram(0);
+        double alpha = this.color.getValue().getAlpha() / 255.0;
+        context.drawRect(0, (1-alpha) * height, width, (1-alpha) * height+1, 0xFFFFFFFF);
+    }
+
+    @Override
+    public boolean mouseClicked(int absMouseX, int absMouseY, double relMouseX, double relMouseY, int mouseButton) {
+        getDomElement().obtainFocus();
+
+        double alpha = 1 - relMouseY / getDomElement().getSize().getHeight();
+        alpha = Layouter.clamp(alpha, 0, 1);
+        int alpha2 = (int) (alpha * 255);
+
+        AColor aColor = new AColor((color.getValue().getRGB() & 0xFFFFFF) | (alpha2 << 24), true);
+        aColor.setChroma(color.getValue().isChroma());
+        aColor.setChromaSpeed(color.getValue().getChromaSpeed());
+        color.setValue(aColor);
+
+
+        return true;
+    }
+
+    @Override
+    public void mouseClickMove(int absMouseX, int absMouseY, double relMouseX, double relMouseY, int clickedMouseButton, long timeSinceLastClick) {
+        double alpha = 1 - relMouseY / getDomElement().getSize().getHeight();
+        alpha = Layouter.clamp(alpha, 0, 1);
+        int alpha2 = (int) (alpha * 255);
+
+        AColor aColor = new AColor((color.getValue().getRGB() & 0xFFFFFF) | (alpha2 << 24), true);
+        aColor.setChroma(color.getValue().isChroma());
+        aColor.setChromaSpeed(color.getValue().getChromaSpeed());
+        color.setValue(aColor);
+    }
+
+    @Override
+    public void mouseReleased(int absMouseX, int absMouseY, double relMouseX, double relMouseY, int state) {
+        if (!getDomElement().isFocused()) return;
+
+        double alpha = 1 - relMouseY / getDomElement().getSize().getHeight();
+        alpha = Layouter.clamp(alpha, 0, 1);
+        int alpha2 = (int) (alpha * 255);
+
+        AColor aColor = new AColor((color.getValue().getRGB() & 0xFFFFFF) | (alpha2 << 24), true);
+        aColor.setChroma(color.getValue().isChroma());
+        aColor.setChromaSpeed(color.getValue().getChromaSpeed());
+        color.setValue(aColor);
+    }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/coloredit/ChromaBar.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/coloredit/ChromaBar.java
new file mode 100644
index 00000000..e72893e1
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/coloredit/ChromaBar.java
@@ -0,0 +1,149 @@
+/*
+ * 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.mod.config.types.coloredit;
+
+import kr.syeyoung.dungeonsguide.mod.config.types.AColor;
+import kr.syeyoung.dungeonsguide.mod.guiv2.BindableAttribute;
+import kr.syeyoung.dungeonsguide.mod.guiv2.DomElement;
+import kr.syeyoung.dungeonsguide.mod.guiv2.Widget;
+import kr.syeyoung.dungeonsguide.mod.guiv2.layouter.Layouter;
+import kr.syeyoung.dungeonsguide.mod.guiv2.primitive.ConstraintBox;
+import kr.syeyoung.dungeonsguide.mod.guiv2.primitive.Rect;
+import kr.syeyoung.dungeonsguide.mod.guiv2.primitive.Size;
+import kr.syeyoung.dungeonsguide.mod.guiv2.renderer.Renderer;
+import kr.syeyoung.dungeonsguide.mod.guiv2.renderer.RenderingContext;
+import kr.syeyoung.dungeonsguide.mod.shader.ShaderManager;
+import kr.syeyoung.dungeonsguide.mod.shader.ShaderProgram;
+import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.client.renderer.Tessellator;
+import net.minecraft.client.renderer.WorldRenderer;
+import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
+import org.lwjgl.opengl.GL20;
+import sun.swing.BakedArrayList;
+
+import java.awt.*;
+import java.util.Collections;
+import java.util.List;
+
+public class ChromaBar extends Widget implements Renderer, Layouter {
+    public final BindableAttribute<AColor> color = new BindableAttribute<>(AColor.class);
+    public ChromaBar(BindableAttribute<AColor> aColorBindableAttribute) {
+        aColorBindableAttribute.exportTo(color);
+    }
+
+    @Override
+    public List<Widget> build(DomElement buildContext) {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public Size layout(DomElement buildContext, ConstraintBox constraintBox) {
+        return new Size(constraintBox.getMaxWidth(), constraintBox.getMaxHeight());
+    }
+
+    @Override
+    public void doRender(int absMouseX, int absMouseY, double relMouseX, double relMouseY, float partialTicks, RenderingContext context, DomElement buildContext) {
+        ShaderProgram shaderProgram = ShaderManager.getShader("shaders/chromaroundrect");
+        shaderProgram.useShader();
+        shaderProgram.uploadUniform("radius", (float)(5.0f * buildContext.getAbsBounds().getWidth() / buildContext.getSize().getWidth()));
+        shaderProgram.uploadUniform("halfSize", (float) buildContext.getAbsBounds().getWidth()/2, (float) buildContext.getAbsBounds().getHeight()/2);
+        shaderProgram.uploadUniform("centerPos",
+                (float) (buildContext.getAbsBounds().getX()+buildContext.getAbsBounds().getWidth()/2),
+                Minecraft.getMinecraft().displayHeight - (float) (buildContext.getAbsBounds().getY() + buildContext.getAbsBounds().getHeight()/2));
+        shaderProgram.uploadUniform("smoothness", 0.0f);
+
+        double width = buildContext.getSize().getWidth();
+        double height = buildContext.getSize().getHeight();
+
+        Tessellator tessellator = Tessellator.getInstance();
+        WorldRenderer worldRenderer = tessellator.getWorldRenderer();
+        GlStateManager.enableBlend();
+        GlStateManager.disableTexture2D();
+        GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0);
+        worldRenderer.begin(7, DefaultVertexFormats.POSITION_COLOR);
+
+        if (this.color.getValue().isChroma()) {
+            Rect abs = getDomElement().getAbsBounds();
+            int r, g, b;
+            int color = RenderUtils.getColorAt(abs.getX(), abs.getY() + abs.getHeight(), this.color.getValue());
+            r = ((color >> 16) & 0xFF);
+            g = ((color >> 8) & 0xFF);
+            b = ((color) & 0xFF);
+            worldRenderer.pos(0, height, 0.0).color(r, g, b, 255).endVertex();
+            worldRenderer.pos(width, height, 0.0).color(r, g, b, 255).endVertex();
+            worldRenderer.pos(width, 0, 0.0).color(r, g, b, 255).endVertex();
+            worldRenderer.pos(0, 0, 0.0).color(r, g, b, 255).endVertex();
+        } else {
+            worldRenderer.pos(0, height, 0.0).color(255, 0, 255, 255).endVertex();
+            worldRenderer.pos(width, height, 0.0).color(255, 0, 255, 255).endVertex();
+            worldRenderer.pos(width, 0, 0.0).color(255, 0, 0, 255).endVertex();
+            worldRenderer.pos(0, 0, 0.0).color(255, 0, 0, 255).endVertex();
+        }
+        tessellator.draw();
+        GlStateManager.enableTexture2D();
+
+        GL20.glUseProgram(0);
+        double alpha = this.color.getValue().getChromaSpeed();
+        context.drawRect(0, (alpha) * height, width, (alpha) * height+1, 0xFFFFFFFF);
+    }
+
+    @Override
+    public boolean mouseClicked(int absMouseX, int absMouseY, double relMouseX, double relMouseY, int mouseButton) {
+        getDomElement().obtainFocus();
+
+        float alpha = (float) (relMouseY / getDomElement().getSize().getHeight());
+        alpha = (float) Layouter.clamp(alpha, 0, 1);
+
+        AColor aColor = new AColor(color.getValue().getRGB(), true);
+        aColor.setChroma(alpha != 0);
+        aColor.setChromaSpeed(alpha);
+        color.setValue(aColor);
+
+
+        return true;
+    }
+
+    @Override
+    public void mouseClickMove(int absMouseX, int absMouseY, double relMouseX, double relMouseY, int clickedMouseButton, long timeSinceLastClick) {
+
+        float alpha = (float) (relMouseY / getDomElement().getSize().getHeight());
+        alpha = (float) Layouter.clamp(alpha, 0, 1);
+
+        AColor aColor = new AColor(color.getValue().getRGB(), true);
+        aColor.setChroma(alpha != 0);
+        aColor.setChromaSpeed(alpha);
+        color.setValue(aColor);
+
+    }
+
+    @Override
+    public void mouseReleased(int absMouseX, int absMouseY, double relMouseX, double relMouseY, int state) {
+        if (!getDomElement().isFocused()) return;
+
+        float alpha = (float) (relMouseY / getDomElement().getSize().getHeight());
+        alpha = (float) Layouter.clamp(alpha, 0, 1);
+
+        AColor aColor = new AColor(color.getValue().getRGB(), true);
+        aColor.setChroma(alpha != 0);
+        aColor.setChromaSpeed(alpha);
+        color.setValue(aColor);
+    }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/coloredit/ColorEditPopup.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/coloredit/ColorEditPopup.java
new file mode 100644
index 00000000..df921580
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/coloredit/ColorEditPopup.java
@@ -0,0 +1,70 @@
+/*
+ * 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.mod.config.types.coloredit;
+
+import kr.syeyoung.dungeonsguide.mod.config.types.AColor;
+import kr.syeyoung.dungeonsguide.mod.guiv2.BindableAttribute;
+import kr.syeyoung.dungeonsguide.mod.guiv2.Widget;
+import kr.syeyoung.dungeonsguide.mod.guiv2.xml.AnnotatedImportOnlyWidget;
+import kr.syeyoung.dungeonsguide.mod.guiv2.xml.annotations.Bind;
+import net.minecraft.util.ResourceLocation;
+import org.apache.commons.lang3.StringUtils;
+
+public class ColorEditPopup extends AnnotatedImportOnlyWidget {
+    @Bind(variableName = "color")
+    public final BindableAttribute<String> color = new BindableAttribute<>(String.class);
+
+    @Bind(variableName = "colorWheel")
+    public final BindableAttribute<Widget> colorWheel = new BindableAttribute<>(Widget.class);
+    @Bind(variableName = "valueBar")
+    public final BindableAttribute<Widget> valueBar = new BindableAttribute<>(Widget.class);
+    @Bind(variableName = "alphaBar")
+    public final BindableAttribute<Widget> alphaBar = new BindableAttribute<>(Widget.class);
+    @Bind(variableName = "chromaBar")
+    public final BindableAttribute<Widget> chromaBar = new BindableAttribute<>(Widget.class);
+
+    public final BindableAttribute<AColor> aColorBindableAttribute = new BindableAttribute<>(AColor.class);
+
+    public ColorEditPopup(BindableAttribute<AColor> colorBindableAttribute) {
+        super(new ResourceLocation("dungeonsguide:gui/config/parameter/colorSet.gui"));
+
+        aColorBindableAttribute.addOnUpdate((old, neu) ->{
+            color.setValue("#" + StringUtils.leftPad(Integer.toHexString(neu.getRGB()).toUpperCase(), 8, '0'));
+        });
+
+        colorBindableAttribute.exportTo(aColorBindableAttribute);
+
+        colorWheel.setValue(new ColorWheel(aColorBindableAttribute));
+        valueBar.setValue(new ValueBar(aColorBindableAttribute));
+        alphaBar.setValue(new AlphaBar(aColorBindableAttribute));
+        chromaBar.setValue(new ChromaBar(aColorBindableAttribute));
+
+
+        color.addOnUpdate((old, neu) -> {
+            try {
+                System.out.println(neu);
+                AColor color1 = new AColor(Integer.parseUnsignedInt(neu.substring(1),16), true);
+                color1.setChromaSpeed(aColorBindableAttribute.getValue().getChromaSpeed());
+                color1.setChroma(aColorBindableAttribute.getValue().isChroma());
+                aColorBindableAttribute.setValue(color1);
+            } catch (Exception e) {
+            }
+        });
+    }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/coloredit/ColorWheel.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/coloredit/ColorWheel.java
new file mode 100644
index 00000000..736cb984
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/coloredit/ColorWheel.java
@@ -0,0 +1,147 @@
+/*
+ * 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.mod.config.types.coloredit;
+
+import kr.syeyoung.dungeonsguide.mod.config.types.AColor;
+import kr.syeyoung.dungeonsguide.mod.guiv2.BindableAttribute;
+import kr.syeyoung.dungeonsguide.mod.guiv2.DomElement;
+import kr.syeyoung.dungeonsguide.mod.guiv2.Widget;
+import kr.syeyoung.dungeonsguide.mod.guiv2.layouter.Layouter;
+import kr.syeyoung.dungeonsguide.mod.guiv2.primitive.ConstraintBox;
+import kr.syeyoung.dungeonsguide.mod.guiv2.primitive.Size;
+import kr.syeyoung.dungeonsguide.mod.guiv2.renderer.Renderer;
+import kr.syeyoung.dungeonsguide.mod.guiv2.renderer.RenderingContext;
+import kr.syeyoung.dungeonsguide.mod.shader.ShaderManager;
+import kr.syeyoung.dungeonsguide.mod.shader.ShaderProgram;
+import net.minecraft.client.Minecraft;
+import net.minecraft.util.MathHelper;
+import org.lwjgl.opengl.GL20;
+
+import java.awt.*;
+import java.util.Collections;
+import java.util.List;
+
+public class ColorWheel extends Widget implements Renderer, Layouter {
+    public final BindableAttribute<AColor> color = new BindableAttribute<>(AColor.class);
+    private final float[] hsv = new float[3];
+    public ColorWheel(BindableAttribute<AColor> aColorBindableAttribute) {
+        color.addOnUpdate((old, neu) -> {
+            Color.RGBtoHSB(neu.getRed(), neu.getGreen(), neu.getBlue(), hsv);
+        });
+        aColorBindableAttribute.exportTo(color);
+    }
+
+    @Override
+    public List<Widget> build(DomElement buildContext) {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public Size layout(DomElement buildContext, ConstraintBox constraintBox) {
+        double len = Math.min(constraintBox.getMaxWidth(), constraintBox.getMaxHeight());
+        return new Size(len, len);
+    }
+
+    @Override
+    public void doRender(int absMouseX, int absMouseY, double relMouseX, double relMouseY, float partialTicks, RenderingContext context, DomElement buildContext) {
+        double rad = buildContext.getAbsBounds().getWidth() / 2.0;
+        ShaderProgram shaderProgram = ShaderManager.getShader("shaders/chromacircle");
+        shaderProgram.useShader();
+        shaderProgram.uploadUniform("radius", (float) rad);
+        shaderProgram.uploadUniform("value", hsv[2]);
+        shaderProgram.uploadUniform("centerPos",
+                (float) (buildContext.getAbsBounds().getX()+buildContext.getAbsBounds().getWidth()/2),
+                Minecraft.getMinecraft().displayHeight - (float) (buildContext.getAbsBounds().getY() + buildContext.getAbsBounds().getHeight()/2));
+        shaderProgram.uploadUniform("smoothness", 0.0f);
+        context.drawRect(0,0,buildContext.getSize().getWidth(), buildContext.getSize().getHeight(), 0xFFFFFFFF);
+        GL20.glUseProgram(0);
+
+        double angle = (hsv[0] - Math.floor(hsv[0])) * Math.PI * 2;
+        double x = Math.sin(angle) * hsv[1] * rad;
+        double y = -Math.cos(angle) * hsv[1] * rad;
+
+        shaderProgram = ShaderManager.getShader("shaders/donut");
+        shaderProgram.useShader();
+        shaderProgram.uploadUniform("radius", 5.0f);
+        shaderProgram.uploadUniform("thickness", 1f);
+        shaderProgram.uploadUniform("centerPos",
+                (float) (buildContext.getAbsBounds().getX()+rad+x),
+                Minecraft.getMinecraft().displayHeight - (float) (buildContext.getAbsBounds().getY() + rad+y));
+        shaderProgram.uploadUniform("smoothness", 0.0f);
+        context.drawRect(0,0,buildContext.getSize().getWidth(), buildContext.getSize().getHeight(), 0xFFFFFFFF);
+        GL20.glUseProgram(0);
+    }
+
+    @Override
+    public boolean mouseClicked(int absMouseX, int absMouseY, double relMouseX, double relMouseY, int mouseButton) {
+
+        double radius = getDomElement().getSize().getWidth()/2;
+        double dx = relMouseX - radius;
+        double dy = relMouseY - radius;
+
+        double hue = Math.atan2(dx, -dy) / (Math.PI * 2);
+        double dist = Math.sqrt(dx * dx + dy * dy) / radius;
+
+        if (dist > 1.0) return false;
+        getDomElement().obtainFocus();
+
+        int rgb = Color.HSBtoRGB((float) hue, (float) dist, hsv[2]);
+        AColor aColor = new AColor((rgb & 0xFFFFFF) | (color.getValue().getRGB() & 0xFF000000), true);
+        aColor.setChroma(color.getValue().isChroma());
+        aColor.setChromaSpeed(color.getValue().getChromaSpeed());
+        color.setValue(aColor);
+
+        return true;
+    }
+
+    @Override
+    public void mouseClickMove(int absMouseX, int absMouseY, double relMouseX, double relMouseY, int clickedMouseButton, long timeSinceLastClick) {
+        double radius = getDomElement().getSize().getWidth()/2;
+        double dx = relMouseX - radius;
+        double dy = relMouseY - radius;
+
+        double hue = Math.atan2(dx, -dy) / (Math.PI * 2);
+        double dist = Math.min(1, Math.sqrt(dx * dx + dy * dy) / radius);
+
+        int rgb = Color.HSBtoRGB((float) hue, (float) dist, hsv[2]);
+        AColor aColor = new AColor((rgb & 0xFFFFFF) | (color.getValue().getRGB() & 0xFF000000), true);
+        aColor.setChroma(color.getValue().isChroma());
+        aColor.setChromaSpeed(color.getValue().getChromaSpeed());
+        color.setValue(aColor);
+
+    }
+
+    @Override
+    public void mouseReleased(int absMouseX, int absMouseY, double relMouseX, double relMouseY, int state) {
+        if (!getDomElement().isFocused()) return;
+        double radius = getDomElement().getSize().getWidth()/2;
+        double dx = relMouseX - radius;
+        double dy = relMouseY - radius;
+
+        double hue = Math.atan2(dx, -dy) / (Math.PI * 2);
+        double dist = Math.min(1, Math.sqrt(dx * dx + dy * dy) / radius);
+
+        int rgb = Color.HSBtoRGB((float) hue, (float) dist, hsv[2]);
+        AColor aColor = new AColor((rgb & 0xFFFFFF) | (color.getValue().getRGB() & 0xFF000000), true);
+        aColor.setChroma(color.getValue().isChroma());
+        aColor.setChromaSpeed(color.getValue().getChromaSpeed());
+        color.setValue(aColor);
+
+    }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/coloredit/ValueBar.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/coloredit/ValueBar.java
new file mode 100644
index 00000000..27a5d260
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/config/types/coloredit/ValueBar.java
@@ -0,0 +1,150 @@
+/*
+ * 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.mod.config.types.coloredit;
+
+import kr.syeyoung.dungeonsguide.mod.config.types.AColor;
+import kr.syeyoung.dungeonsguide.mod.guiv2.BindableAttribute;
+import kr.syeyoung.dungeonsguide.mod.guiv2.DomElement;
+import kr.syeyoung.dungeonsguide.mod.guiv2.Widget;
+import kr.syeyoung.dungeonsguide.mod.guiv2.layouter.Layouter;
+import kr.syeyoung.dungeonsguide.mod.guiv2.primitive.ConstraintBox;
+import kr.syeyoung.dungeonsguide.mod.guiv2.primitive.Size;
+import kr.syeyoung.dungeonsguide.mod.guiv2.renderer.Renderer;
+import kr.syeyoung.dungeonsguide.mod.guiv2.renderer.RenderingContext;
+import kr.syeyoung.dungeonsguide.mod.shader.ShaderManager;
+import kr.syeyoung.dungeonsguide.mod.shader.ShaderProgram;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.client.renderer.Tessellator;
+import net.minecraft.client.renderer.WorldRenderer;
+import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
+import net.minecraft.util.MathHelper;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL20;
+
+import java.awt.*;
+import java.util.Collections;
+import java.util.List;
+
+public class ValueBar extends Widget implements Renderer, Layouter {
+    public final BindableAttribute<AColor> color = new BindableAttribute<>(AColor.class);
+
+    private final float[] hsv = new float[3];
+    public ValueBar(BindableAttribute<AColor> aColorBindableAttribute) {
+        color.addOnUpdate((old, neu) -> {
+            Color.RGBtoHSB(neu.getRed(), neu.getGreen(), neu.getBlue(), hsv);
+        });
+        aColorBindableAttribute.exportTo(color);
+    }
+
+    @Override
+    public List<Widget> build(DomElement buildContext) {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public Size layout(DomElement buildContext, ConstraintBox constraintBox) {
+        return new Size(constraintBox.getMaxWidth(), constraintBox.getMaxHeight());
+    }
+
+    @Override
+    public void doRender(int absMouseX, int absMouseY, double relMouseX, double relMouseY, float partialTicks, RenderingContext context, DomElement buildContext) {
+        ShaderProgram shaderProgram = ShaderManager.getShader("shaders/roundrect");
+        shaderProgram.useShader();
+        shaderProgram.uploadUniform("radius", (float)(5.0f * buildContext.getAbsBounds().getWidth() / buildContext.getSize().getWidth()));
+        shaderProgram.uploadUniform("halfSize", (float) buildContext.getAbsBounds().getWidth()/2, (float) buildContext.getAbsBounds().getHeight()/2);
+        shaderProgram.uploadUniform("centerPos",
+                (float) (buildContext.getAbsBounds().getX()+buildContext.getAbsBounds().getWidth()/2),
+                Minecraft.getMinecraft().displayHeight - (float) (buildContext.getAbsBounds().getY() + buildContext.getAbsBounds().getHeight()/2));
+        shaderProgram.uploadUniform("smoothness", 0.0f);
+
+        Tessellator tessellator = Tessellator.getInstance();
+        WorldRenderer worldRenderer = tessellator.getWorldRenderer();
+        GlStateManager.enableBlend();
+        GlStateManager.disableTexture2D();
+        GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0);
+        double width = buildContext.getSize().getWidth();
+        double height = buildContext.getSize().getHeight();
+        worldRenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR);
+
+        int r,g,b;
+        int color = Color.HSBtoRGB(hsv[0], hsv[1], 0);
+        r = ((color >> 16) &0xFF);
+        g = ((color >> 8) &0xFF) ;
+        b= ((color) &0xFF) ;
+        worldRenderer.pos(0, height, 0.0).color(r,g,b,255).endVertex();
+        worldRenderer.pos(width, height, 0.0).color(r,g,b,255).endVertex();
+        color = Color.HSBtoRGB(hsv[0], hsv[1], 1.0f);
+        r = ((color >> 16) &0xFF);
+        g = ((color >> 8) &0xFF);
+        b= ((color) &0xFF);
+        worldRenderer.pos(width, 0, 0.0).color(r,g,b,255).endVertex();
+        worldRenderer.pos(0, 0, 0.0).color(r,g,b,255).endVertex();
+        tessellator.draw();
+        GlStateManager.enableTexture2D();
+
+        GL20.glUseProgram(0);
+
+        context.drawRect(0, (1-hsv[2]) * height, width, (1-hsv[2]) * height+1, 0xFFFFFFFF);
+    }
+
+    @Override
+    public boolean mouseClicked(int absMouseX, int absMouseY, double relMouseX, double relMouseY, int mouseButton) {
+        getDomElement().obtainFocus();
+
+        double value = 1 - relMouseY / getDomElement().getSize().getHeight();
+        value = Layouter.clamp(value, 0, 1);
+
+        int rgb = Color.HSBtoRGB(hsv[0], hsv[1], (float) value);
+        AColor aColor = new AColor((rgb & 0xFFFFFF) | (color.getValue().getRGB() & 0xFF000000), true);
+        aColor.setChroma(color.getValue().isChroma());
+        aColor.setChromaSpeed(color.getValue().getChromaSpeed());
+        color.setValue(aColor);
+
+
+        return true;
+    }
+
+    @Override
+    public void mouseClickMove(int absMouseX, int absMouseY, double relMouseX, double relMouseY, int clickedMouseButton, long timeSinceLastClick) {
+
+        double value = 1 - relMouseY / getDomElement().getSize().getHeight();
+        value = Layouter.clamp(value, 0, 1);
+
+        int rgb = Color.HSBtoRGB(hsv[0], hsv[1], (float) value);
+        AColor aColor = new AColor((rgb & 0xFFFFFF) | (color.getValue().getRGB() & 0xFF000000), true);
+        aColor.setChroma(color.getValue().isChroma());
+        aColor.setChromaSpeed(color.getValue().getChromaSpeed());
+        color.setValue(aColor);
+    }
+
+    @Override
+    public void mouseReleased(int absMouseX, int absMouseY, double relMouseX, double relMouseY, int state) {
+        if (!getDomElement().isFocused()) return;
+
+        double value = 1 - relMouseY / getDomElement().getSize().getHeight();
+        value = Layouter.clamp(value, 0, 1);
+
+        int rgb = Color.HSBtoRGB(hsv[0], hsv[1], (float) value);
+        AColor aColor = new AColor((rgb & 0xFFFFFF) | (color.getValue().getRGB() & 0xFF000000), true);
+        aColor.setChroma(color.getValue().isChroma());
+        aColor.setChromaSpeed(color.getValue().getChromaSpeed());
+        color.setValue(aColor);
+    }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/AbstractFeature.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/AbstractFeature.java
index ad24b68f..363fd24e 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/AbstractFeature.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/AbstractFeature.java
@@ -21,13 +21,8 @@ package kr.syeyoung.dungeonsguide.mod.features;
 import com.google.common.base.Supplier;
 import com.google.gson.JsonElement;
 import com.google.gson.JsonObject;
-import kr.syeyoung.dungeonsguide.mod.config.guiconfig.ConfigPanelCreator;
-import kr.syeyoung.dungeonsguide.mod.config.guiconfig.MFeatureEdit;
-import kr.syeyoung.dungeonsguide.mod.config.guiconfig.MParameterEdit;
-import kr.syeyoung.dungeonsguide.mod.config.guiconfig.RootConfigPanel;
 import kr.syeyoung.dungeonsguide.mod.config.guiconfig.configv3.DefaultConfigurePageWidget;
-import kr.syeyoung.dungeonsguide.mod.config.types.TypeConverter;
-import kr.syeyoung.dungeonsguide.mod.config.types.TypeConverterRegistry;
+import kr.syeyoung.dungeonsguide.mod.config.types.FeatureTypeHandler;
 import kr.syeyoung.dungeonsguide.mod.gui.MPanel;
 import kr.syeyoung.dungeonsguide.mod.guiv2.Widget;
 import lombok.Getter;
@@ -78,36 +73,22 @@ public abstract class AbstractFeature implements IFeature {
             parameterEntry.getValue().setToDefault();
             JsonElement element = jsonObject.get(parameterEntry.getKey());
             if (element == null) continue;
-            TypeConverter typeConverter = TypeConverterRegistry.getTypeConverter(parameterEntry.getValue().getValue_type());
-            parameterEntry.getValue().setValue(typeConverter.deserialize(element));
+            FeatureTypeHandler featureTypeHandler = parameterEntry.getValue().getFeatureTypeHandler();
+            parameterEntry.getValue().setValue(featureTypeHandler.deserialize(element));
         }
     }
 
     public JsonObject saveConfig() {
         JsonObject object = new JsonObject();
         for (Map.Entry<String, FeatureParameter> parameterEntry : parameters.entrySet()) {
-            TypeConverter typeConverter = TypeConverterRegistry.getTypeConverter(parameterEntry.getValue().getValue_type());
-            JsonElement obj = typeConverter.serialize(parameterEntry.getValue().getValue());
+            FeatureTypeHandler featureTypeHandler =  parameterEntry.getValue().getFeatureTypeHandler();
+            JsonElement obj = featureTypeHandler.serialize(parameterEntry.getValue().getValue());
             object.add(parameterEntry.getKey(), obj);
         }
         object.addProperty("$enabled", isEnabled());
         return object;
     }
 
-    public String getEditRoute(RootConfigPanel rootConfigPanel) {
-        ConfigPanelCreator.map.put("base." + key , new Supplier<MPanel>() {
-            @Override
-            public MPanel get() {
-                MFeatureEdit featureEdit = new MFeatureEdit(AbstractFeature.this, rootConfigPanel);
-                for (FeatureParameter parameter: getParameters()) {
-                    featureEdit.addParameterEdit(parameter.getKey(), new MParameterEdit(AbstractFeature.this, parameter, rootConfigPanel));
-                }
-                return featureEdit;
-            }
-        });
-        return "base." + key ;
-    }
-
     public Widget getConfigureWidget() {
         List<Widget> widgets = new LinkedList<>();
         setupConfigureWidget(widgets);
@@ -116,7 +97,12 @@ public abstract class AbstractFeature implements IFeature {
     }
 
     public void setupConfigureWidget(List<Widget> widgets) {
-
+        for (FeatureParameter parameter : getParameters()) {
+            if (parameter.getWidgetGenerator() == null) continue;;
+            Widget widget = (Widget) parameter.getWidgetGenerator().apply(parameter);
+            if (widget == null) continue;;
+            widgets.add(widget);
+        }
     }
 
     public String getIcon() {
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/AbstractHUDFeature.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/AbstractHUDFeature.java
index 2b990d8e..b5b1fafb 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/AbstractHUDFeature.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/AbstractHUDFeature.java
@@ -19,19 +19,29 @@
 package kr.syeyoung.dungeonsguide.mod.features;
 
 import com.google.gson.JsonObject;
+import kr.syeyoung.dungeonsguide.mod.config.guiconfig.configv3.MainConfigWidget;
 import kr.syeyoung.dungeonsguide.mod.config.types.GUIPosition;
-import kr.syeyoung.dungeonsguide.mod.config.types.TypeConverterRegistry;
+import kr.syeyoung.dungeonsguide.mod.config.types.TCGUIPosition;
+import kr.syeyoung.dungeonsguide.mod.guiv2.BindableAttribute;
 import kr.syeyoung.dungeonsguide.mod.guiv2.DomElement;
+import kr.syeyoung.dungeonsguide.mod.guiv2.GuiScreenAdapter;
 import kr.syeyoung.dungeonsguide.mod.guiv2.Widget;
+import kr.syeyoung.dungeonsguide.mod.guiv2.elements.GlobalHUDScale;
+import kr.syeyoung.dungeonsguide.mod.guiv2.elements.Navigator;
 import kr.syeyoung.dungeonsguide.mod.guiv2.elements.Text;
 import kr.syeyoung.dungeonsguide.mod.guiv2.layouter.Layouter;
 import kr.syeyoung.dungeonsguide.mod.guiv2.primitive.ConstraintBox;
 import kr.syeyoung.dungeonsguide.mod.guiv2.primitive.Size;
 import kr.syeyoung.dungeonsguide.mod.guiv2.renderer.Renderer;
 import kr.syeyoung.dungeonsguide.mod.guiv2.renderer.RenderingContext;
+import kr.syeyoung.dungeonsguide.mod.guiv2.xml.AnnotatedImportOnlyWidget;
+import kr.syeyoung.dungeonsguide.mod.guiv2.xml.annotations.Bind;
+import kr.syeyoung.dungeonsguide.mod.guiv2.xml.annotations.On;
 import lombok.Getter;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.audio.PositionedSoundRecord;
+import net.minecraft.util.ResourceLocation;
 
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
@@ -102,19 +112,22 @@ public abstract class AbstractHUDFeature extends AbstractGuiFeature {
     @Override
     public void loadConfig(JsonObject jsonObject) {
         super.loadConfig(jsonObject);
-        GUIPosition position = TypeConverterRegistry.getTypeConverter("guipos", GUIPosition.class).deserialize(jsonObject.get("$pos"));
+        GUIPosition position = TCGUIPosition.INSTANCE.deserialize(jsonObject.get("$pos"));
         if (position != null) setFeatureRect(position);
     }
 
     @Override
     public JsonObject saveConfig() {
         JsonObject object = super.saveConfig();
-        object.add("$pos", TypeConverterRegistry.getTypeConverter("guipos", GUIPosition.class).serialize(featureRect));
+        object.add("$pos", TCGUIPosition.INSTANCE.serialize(featureRect));
         return object;
     }
 
     public void getTooltipForEditor(List<Widget> widgets) {
         widgets.add(new Text(getName(), 0xFFFFFFFF, Text.TextAlign.CENTER, Text.WordBreak.WORD, 1.0, 8.0));
+        widgets.add(new QuickEnable(this));
+        if (getConfigureWidget() != null)
+            widgets.add(new QuickConfigure(this));
 //        mPanels.add(new MButton() {
 //            {
 //                setText("Edit");
@@ -142,4 +155,38 @@ public abstract class AbstractHUDFeature extends AbstractGuiFeature {
 //            }); }
 //        }));
     }
+
+    public static class QuickEnable extends AnnotatedImportOnlyWidget {
+        @Bind(
+                variableName = "enabled"
+        )
+        public final BindableAttribute<Boolean> enabled = new BindableAttribute<Boolean>(Boolean.class);
+        public QuickEnable(AbstractHUDFeature abstractHUDFeature) {
+            super(new ResourceLocation("dungeonsguide:gui/config/popup/quickEnable.gui"));
+            enabled.setValue(abstractHUDFeature.isEnabled());
+            enabled.addOnUpdate((old, neu) -> {
+                Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F));
+                abstractHUDFeature.setEnabled(neu);
+            });
+        }
+    }
+    public static class QuickConfigure extends AnnotatedImportOnlyWidget {
+        private AbstractHUDFeature abstractHUDFeature;
+        public QuickConfigure(AbstractHUDFeature abstractHUDFeature) {
+            super(new ResourceLocation("dungeonsguide:gui/config/popup/quickEdit.gui"));
+            this.abstractHUDFeature = abstractHUDFeature;
+        }
+
+        @On(functionName = "configure")
+        public void configure() {
+            Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F));
+            MainConfigWidget mainConfigWidget = new MainConfigWidget();
+            GuiScreenAdapter adapter = new GuiScreenAdapter(new GlobalHUDScale(mainConfigWidget));
+            Minecraft.getMinecraft().displayGuiScreen(adapter);
+
+            Navigator.getNavigator(mainConfigWidget.getDomElement()).openPage(
+                    abstractHUDFeature.getConfigureWidget()
+            );
+        }
+    }
 }
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/FeatureParameter.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/FeatureParameter.java
index bb8fd85a..22a16a11 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/FeatureParameter.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/FeatureParameter.java
@@ -18,12 +18,13 @@
 
 package kr.syeyoung.dungeonsguide.mod.features;
 
-import kr.syeyoung.dungeonsguide.mod.config.types.TypeConverter;
-import kr.syeyoung.dungeonsguide.mod.config.types.TypeConverterRegistry;
+import kr.syeyoung.dungeonsguide.mod.config.types.FeatureTypeHandler;
+import kr.syeyoung.dungeonsguide.mod.guiv2.Widget;
 import lombok.AllArgsConstructor;
 import lombok.Data;
 
 import java.util.function.Consumer;
+import java.util.function.Function;
 
 @Data
 @AllArgsConstructor
@@ -32,31 +33,41 @@ public class FeatureParameter<T> {
     private String name;
     private String description;
     private T value;
-
-
     private T default_value;
-    private String value_type;
+    private FeatureTypeHandler<T> featureTypeHandler;
+    private Function<FeatureParameter<T>, Widget> widgetGenerator;
     private Consumer<T> changedCallback;
+    private String icon;
 
-    public FeatureParameter(String key, String name, String description, T default_value, String value_type) {
-        this(key, name, description,default_value, value_type, null);
+    public FeatureParameter(String key, String name, String description, T default_value, FeatureTypeHandler<T> converter) {
+        this(key, name, description,default_value, converter, null);
     }
 
-    public FeatureParameter(String key, String name, String description, T default_value, String value_type, Consumer<T> changedCallback) {
+    public FeatureParameter(String key, String name, String description, T default_value, FeatureTypeHandler<T> converter, Consumer<T> changedCallback) {
         this.key = key;
         this.name = name;
         this.default_value = default_value;
         this.description = description;
-        this.value_type = value_type;
+        this.featureTypeHandler = converter;
+        this.widgetGenerator = featureTypeHandler::createDefaultWidgetFor;
         if(changedCallback != null){
             this.changedCallback = changedCallback;
             changedCallback.accept(default_value);
         }
     }
 
+    public FeatureParameter<T> setWidgetGenerator(Function<FeatureParameter<T>, Widget> widgetGenerator) {
+        this.widgetGenerator = widgetGenerator;
+        return this;
+    }
+
+    public FeatureParameter<T> setIcon(String icon) {
+        this.icon = icon;
+        return this;
+    }
+
     public void setToDefault() {
-        TypeConverter<T> typeConverter = TypeConverterRegistry.getTypeConverter(getValue_type());
-        value = (T) typeConverter.deserialize(typeConverter.serialize(default_value));
+        value = (T) featureTypeHandler.deserialize(featureTypeHandler.serialize(default_value));
     }
 
     public T getValue() {
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/FeatureRegistry.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/FeatureRegistry.java
index b670b72a..ee977619 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/FeatureRegistry.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/FeatureRegistry.java
@@ -18,6 +18,9 @@
 
 package kr.syeyoung.dungeonsguide.mod.features;
 
+import kr.syeyoung.dungeonsguide.mod.config.types.TCBoolean;
+import kr.syeyoung.dungeonsguide.mod.config.types.TCFloat;
+import kr.syeyoung.dungeonsguide.mod.config.types.TCKeybind;
 import kr.syeyoung.dungeonsguide.mod.events.annotations.EventHandlerRegistry;
 import kr.syeyoung.dungeonsguide.mod.features.impl.advanced.*;
 import kr.syeyoung.dungeonsguide.mod.features.impl.boss.*;
@@ -132,17 +135,17 @@ public class FeatureRegistry {
     public static final PathfindLineProperties SECRET_BLOOD_RUSH_LINE_PROPERTIES = register(new PathfindLineProperties("Dungeon.Secrets.Blood Rush", "Blood Rush Line Settings", "Line Settings to be used", "secret.lineproperties.bloodrush", false, SECRET_LINE_PROPERTIES_GLOBAL));
     public static final FeatureBloodRush SECRET_BLOOD_RUSH = register(new FeatureBloodRush());
     public static final SimpleFeature SECRET_NEXT_KEY = register(new SimpleFeature("Dungeon.Secrets.Legacy AutoPathfind", "Auto Pathfind to new secret upon pressing a key", "Auto browse the best next secret when you press key.\nPress settings to edit the key", "secret.keyfornext", false) {{
-        addParameter("key", new FeatureParameter<Integer>("key", "Key", "Press to navigate to next best secret", Keyboard.KEY_NONE, "keybind"));
+        addParameter("key", new FeatureParameter<Integer>("key", "Key", "Press to navigate to next best secret", Keyboard.KEY_NONE, TCKeybind.INSTANCE));
     }});
 
     public static final SimpleFeature GLOBAL_HUD_SCALE = register(new SimpleFeature("Misc", "Global HUD Scale", "Configure to use gui scale from Minecraft or specify custom one", "hud.globalscale", false) {
         private boolean init = false;
         {
-            addParameter("mc", new FeatureParameter<Boolean>("mc", "Minecraft", "Enable to use minecraft default hud scale", true, "boolean", a -> {
+            addParameter("mc", new FeatureParameter<Boolean>("mc", "Minecraft", "Enable to use minecraft default hud scale", true, TCBoolean.INSTANCE, a -> {
                 if (init)
                 OverlayManager.getEventHandler().guiResize(null);
             }));
-            addParameter("scale", new FeatureParameter<Float>("scale", "Scale", "Custom HUD Scale",1.0f, "float", a -> {
+            addParameter("scale", new FeatureParameter<Float>("scale", "Scale", "Custom HUD Scale",1.0f, TCFloat.INSTANCE, a -> {
                 if (init)
                 OverlayManager.getEventHandler().guiResize(null);
 
@@ -197,7 +200,7 @@ public class FeatureRegistry {
     public static final FeatureNicknamePrefix COSMETIC_PREFIX = register(new FeatureNicknamePrefix());
     public static final SimpleFeature DISCORD_RICHPRESENCE = register(new SimpleFeature("Discord", "Discord RPC", "Enable Discord rich presence", "advanced.discordrichpresence", true) {
         {
-            addParameter("disablenotskyblock", new FeatureParameter<Boolean>("disablenotskyblock", "Disable When not on Skyblock", "Disable When not on skyblock", false, "boolean"));
+            addParameter("disablenotskyblock", new FeatureParameter<Boolean>("disablenotskyblock", "Disable When not on Skyblock", "Disable When not on skyblock", false, TCBoolean.INSTANCE));
         }
     });
     public static final PartyInviteViewer DISCORD_ASKTOJOIN = register(new PartyInviteViewer());
@@ -205,7 +208,7 @@ public class FeatureRegistry {
     public static final FeatureDebug DEBUG = register(new FeatureDebug());
     public static final SimpleFeature ADVANCED_ROOMEDIT = register(new SimpleFeature("Debug", "Room Edit", "Allow editing dungeon rooms\n\nWarning: using this feature can break or freeze your Minecraft\nThis is for advanced users only", "advanced.roomedit", false) {
         {
-            addParameter("key", new FeatureParameter<Integer>("key", "Key", "Press to edit room", Keyboard.KEY_R, "keybind"));
+            addParameter("key", new FeatureParameter<Integer>("key", "Key", "Press to edit room", Keyboard.KEY_R, TCKeybind.INSTANCE));
         }
     });
     public static final FeatureRoomDebugInfo ADVANCED_DEBUG_ROOM = register(new FeatureRoomDebugInfo());
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/advanced/FeatureDebuggableMap.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/advanced/FeatureDebuggableMap.java
index 35adaafe..ac4f0581 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/advanced/FeatureDebuggableMap.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/advanced/FeatureDebuggableMap.java
@@ -23,7 +23,6 @@ import kr.syeyoung.dungeonsguide.mod.DungeonsGuide;
 import kr.syeyoung.dungeonsguide.mod.SkyblockStatus;
 import kr.syeyoung.dungeonsguide.mod.features.FeatureRegistry;
 import kr.syeyoung.dungeonsguide.mod.features.RawRenderingGuiFeature;
-import kr.syeyoung.dungeonsguide.mod.guiv2.primitive.Size;
 import kr.syeyoung.dungeonsguide.mod.utils.MapUtils;
 import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils;
 import net.minecraft.client.Minecraft;
@@ -33,13 +32,8 @@ import net.minecraft.client.gui.GuiScreen;
 import net.minecraft.client.renderer.GlStateManager;
 import net.minecraft.client.renderer.texture.DynamicTexture;
 import net.minecraft.util.ResourceLocation;
-import net.minecraftforge.fml.client.config.GuiUtils;
-import org.lwjgl.input.Mouse;
 import org.lwjgl.opengl.GL11;
 
-import java.awt.*;
-import java.util.Arrays;
-
 public class FeatureDebuggableMap extends RawRenderingGuiFeature {
     public FeatureDebuggableMap() {
         super("Debug", "Display Debug Info included map", "ONLY WORKS WITH SECRET SETTING", "advanced.debug.map", true, 128, 128);
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/advanced/FeatureTestPeople.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/advanced/FeatureTestPeople.java
index 40ddde89..7e1d6096 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/advanced/FeatureTestPeople.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/advanced/FeatureTestPeople.java
@@ -21,6 +21,7 @@ package kr.syeyoung.dungeonsguide.mod.features.impl.advanced;
 import com.mojang.authlib.GameProfile;
 import com.mojang.authlib.minecraft.MinecraftProfileTexture;
 import kr.syeyoung.dungeonsguide.mod.DungeonsGuide;
+import kr.syeyoung.dungeonsguide.mod.config.types.TCFloat;
 import kr.syeyoung.dungeonsguide.mod.events.annotations.DGEventHandler;
 import kr.syeyoung.dungeonsguide.mod.events.impl.DungeonStartedEvent;
 import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
@@ -72,7 +73,7 @@ public class FeatureTestPeople extends RawRenderingGuiFeature {
         super("Dungeon", "Feature test", "NOU", "", false, 200, 100);
 
 
-        addParameter("scale", new FeatureParameter<>("scale", "Scale", "Scale", 2.0f, "float", nval -> this.scale = nval));
+        addParameter("scale", new FeatureParameter<>("scale", "Scale", "Scale", 2.0f, TCFloat.INSTANCE, nval -> this.scale = nval));
 
 //        (new Thread(() -> {
 //            while (true){
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/boss/FeatureBossHealth.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/boss/FeatureBossHealth.java
index 6cde5094..9c534176 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/boss/FeatureBossHealth.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/boss/FeatureBossHealth.java
@@ -22,6 +22,7 @@ package kr.syeyoung.dungeonsguide.mod.features.impl.boss;
 import kr.syeyoung.dungeonsguide.mod.DungeonsGuide;
 import kr.syeyoung.dungeonsguide.mod.SkyblockStatus;
 import kr.syeyoung.dungeonsguide.mod.config.types.AColor;
+import kr.syeyoung.dungeonsguide.mod.config.types.TCBoolean;
 import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bossfight.HealthData;
 import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
 import kr.syeyoung.dungeonsguide.mod.features.text.StyledText;
@@ -37,9 +38,9 @@ public class FeatureBossHealth extends TextHUDFeature {
     public FeatureBossHealth() {
         super("Dungeon.Bossfight", "Display Boss(es) Health", "Show the health of boss and minibosses in bossfight (Guardians, Priests..)", "bossfight.health");
         this.setEnabled(true);
-        addParameter("totalHealth", new FeatureParameter<Boolean>("totalHealth", "show total health", "Show total health along with current health", false, "boolean", nval -> totalHealth = nval));
-        addParameter("formatHealth", new FeatureParameter<Boolean>("formatHealth", "format health", "1234568 -> 1m", true, "boolean", nval -> formatHealth = nval));
-        addParameter("ignoreInattackable", new FeatureParameter<Boolean>("ignoreInattackable", "Don't show health of in-attackable enemy", "For example, do not show guardians health when they're not attackable", false, "boolean", nval -> ignoreInattackable = nval));
+        addParameter("totalHealth", new FeatureParameter<Boolean>("totalHealth", "show total health", "Show total health along with current health", false, TCBoolean.INSTANCE, nval -> totalHealth = nval));
+        addParameter("formatHealth", new FeatureParameter<Boolean>("formatHealth", "format health", "1234568 -> 1m", true, TCBoolean.INSTANCE, nval -> formatHealth = nval));
+        addParameter("ignoreInattackable", new FeatureParameter<Boolean>("ignoreInattackable", "Don't show health of in-attackable enemy", "For example, do not show guardians health when they're not attackable", false, TCBoolean.INSTANCE, nval -> ignoreInattackable = nval));
 
         getStyles().add(new TextStyle("title", new AColor(0x00, 0xAA,0xAA,255), new AColor(0, 0,0,0), false));
         getStyles().add(new TextStyle("separator", new AColor(0x55, 0x55,0x55,255), new AColor(0, 0,0,0), false));
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/boss/FeatureBoxRealLivid.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/boss/FeatureBoxRealLivid.java
index c60e1336..44adc6b3 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/boss/FeatureBoxRealLivid.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/boss/FeatureBoxRealLivid.java
@@ -22,6 +22,7 @@ package kr.syeyoung.dungeonsguide.mod.features.impl.boss;
 import kr.syeyoung.dungeonsguide.mod.DungeonsGuide;
 import kr.syeyoung.dungeonsguide.mod.SkyblockStatus;
 import kr.syeyoung.dungeonsguide.mod.config.types.AColor;
+import kr.syeyoung.dungeonsguide.mod.config.types.TCAColor;
 import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bossfight.BossfightProcessorLivid;
 import kr.syeyoung.dungeonsguide.mod.events.annotations.DGEventHandler;
 import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
@@ -35,7 +36,7 @@ import net.minecraftforge.client.event.RenderWorldLastEvent;
 public class FeatureBoxRealLivid extends SimpleFeature {
     public FeatureBoxRealLivid() {
         super("Dungeon.Bossfight.Floor 5", "Box Real Livid", "Box Real Livid in bossfight", "Dungeon.Bossfight.realLividBox", true);
-        addParameter("color", new FeatureParameter<AColor>("color", "Highlight Color", "Highlight Color of Livid", new AColor(0,255,0,150), "acolor", nval -> color = nval));
+        addParameter("color", new FeatureParameter<AColor>("color", "Highlight Color", "Highlight Color of Livid", new AColor(0,255,0,150), TCAColor.INSTANCE, nval -> color = nval));
     }
 
     AColor color = null;
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/boss/FeatureHideAnimals.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/boss/FeatureHideAnimals.java
index 06b7e39c..b99b29e9 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/boss/FeatureHideAnimals.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/boss/FeatureHideAnimals.java
@@ -21,6 +21,7 @@ package kr.syeyoung.dungeonsguide.mod.features.impl.boss;
 
 import kr.syeyoung.dungeonsguide.mod.DungeonsGuide;
 import kr.syeyoung.dungeonsguide.mod.SkyblockStatus;
+import kr.syeyoung.dungeonsguide.mod.config.types.TCBoolean;
 import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bossfight.BossfightProcessorThorn;
 import kr.syeyoung.dungeonsguide.mod.events.annotations.DGEventHandler;
 import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
@@ -32,11 +33,11 @@ import net.minecraftforge.client.event.RenderLivingEvent;
 public class FeatureHideAnimals extends SimpleFeature  {
     public FeatureHideAnimals() {
         super("Dungeon.Bossfight.Floor 4", "Hide animals on f4", "Hide Spirit Animals on F4. \nClick on Edit for precise setting", "bossfight.hideanimals", false);
-        addParameter("sheep", new FeatureParameter<Boolean>("sheep", "Hide Sheep", "Hide Sheep", true, "boolean", nval -> sheep = nval));
-        addParameter("cow", new FeatureParameter<Boolean>("cow", "Hide Cows", "Hide Cows", true, "boolean", nval -> cow = nval));
-        addParameter("chicken", new FeatureParameter<Boolean>("chicken", "Hide Chickens", "Hide Chickens", true, "boolean", nval -> chicken = nval));
-        addParameter("wolf", new FeatureParameter<Boolean>("wolf", "Hide Wolves", "Hide Wolves", true, "boolean", nval -> wolf = nval));
-        addParameter("rabbit", new FeatureParameter<Boolean>("rabbit", "Hide Rabbits", "Hide Rabbits", true, "boolean", nval -> rabbit = nval));
+        addParameter("sheep", new FeatureParameter<Boolean>("sheep", "Hide Sheep", "Hide Sheep", true, TCBoolean.INSTANCE, nval -> sheep = nval));
+        addParameter("cow", new FeatureParameter<Boolean>("cow", "Hide Cows", "Hide Cows", true, TCBoolean.INSTANCE, nval -> cow = nval));
+        addParameter("chicken", new FeatureParameter<Boolean>("chicken", "Hide Chickens", "Hide Chickens", true, TCBoolean.INSTANCE, nval -> chicken = nval));
+        addParameter("wolf", new FeatureParameter<Boolean>("wolf", "Hide Wolves", "Hide Wolves", true, TCBoolean.INSTANCE, nval -> wolf = nval));
+        addParameter("rabbit", new FeatureParameter<Boolean>("rabbit", "Hide Rabbits", "Hide Rabbits", true, TCBoolean.INSTANCE, nval -> rabbit = nval));
     }
 
     boolean sheep;
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/boss/FeatureWarningOnPortal.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/boss/FeatureWarningOnPortal.java
index 35607d58..e789d8ea 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/boss/FeatureWarningOnPortal.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/boss/FeatureWarningOnPortal.java
@@ -18,14 +18,10 @@
 
 package kr.syeyoung.dungeonsguide.mod.features.impl.boss;
 
-import com.google.common.base.Supplier;
 import kr.syeyoung.dungeonsguide.mod.DungeonsGuide;
 import kr.syeyoung.dungeonsguide.mod.SkyblockStatus;
-import kr.syeyoung.dungeonsguide.mod.config.guiconfig.ConfigPanelCreator;
-import kr.syeyoung.dungeonsguide.mod.config.guiconfig.MFeatureEdit;
-import kr.syeyoung.dungeonsguide.mod.config.guiconfig.MParameterEdit;
-import kr.syeyoung.dungeonsguide.mod.config.guiconfig.RootConfigPanel;
 import kr.syeyoung.dungeonsguide.mod.config.types.AColor;
+import kr.syeyoung.dungeonsguide.mod.config.types.TCTextStyleList;
 import kr.syeyoung.dungeonsguide.mod.dungeon.DungeonContext;
 import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom;
 import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
@@ -36,7 +32,7 @@ import kr.syeyoung.dungeonsguide.mod.features.text.PanelTextParameterConfig;
 import kr.syeyoung.dungeonsguide.mod.features.text.StyledText;
 import kr.syeyoung.dungeonsguide.mod.features.text.StyledTextProvider;
 import kr.syeyoung.dungeonsguide.mod.features.text.TextStyle;
-import kr.syeyoung.dungeonsguide.mod.gui.MPanel;
+import kr.syeyoung.dungeonsguide.mod.guiv2.elements.CompatLayer;
 import kr.syeyoung.dungeonsguide.mod.utils.TextUtils;
 
 import java.util.ArrayList;
@@ -47,7 +43,8 @@ import java.util.Map;
 public class FeatureWarningOnPortal extends SimpleFeature implements StyledTextProvider {
     public FeatureWarningOnPortal() {
         super("Dungeon.Blood Room", "Score Warning on Watcher portal", "Display warnings such as\n- 'NOT ALL ROOMS DISCOVERED'\n- 'NOT ALL ROOMS COMPLETED'\n- 'Expected Score: 304'\n- 'MISSING 3 CRYPTS'\non portal", "bossfight.warningonportal");
-        addParameter("textStyles", new FeatureParameter<List<TextStyle>>("textStyles", "", "", new ArrayList<TextStyle>(), "list_textStyle"));
+        addParameter("textStyles", new FeatureParameter<List<TextStyle>>("textStyles", "", "", new ArrayList<TextStyle>(), TCTextStyleList.INSTANCE)
+                .setWidgetGenerator(param -> new CompatLayer(new PanelTextParameterConfig(FeatureWarningOnPortal.this))));
         getStyles().add(new TextStyle("warning", new AColor(255, 0,0,255), new AColor(255, 255,255,255), false));
         getStyles().add(new TextStyle("field_name", new AColor(255, 72,255,255), new AColor(0, 0,0,0), false));
         getStyles().add(new TextStyle("field_separator", new AColor(204, 204,204,255), new AColor(0, 0,0,0), false));
@@ -187,20 +184,4 @@ public class FeatureWarningOnPortal extends SimpleFeature implements StyledTextP
     }
 
 
-    @Override
-    public String getEditRoute(RootConfigPanel rootConfigPanel) {
-        ConfigPanelCreator.map.put("base." + getKey() , new Supplier<MPanel>() {
-            @Override
-            public MPanel get() {
-                MFeatureEdit featureEdit = new MFeatureEdit(FeatureWarningOnPortal.this, rootConfigPanel);
-                featureEdit.addParameterEdit("textStyles", new PanelTextParameterConfig(FeatureWarningOnPortal.this));
-                for (FeatureParameter parameter: getParameters()) {
-                    if (parameter.getKey().equals("textStyles")) continue;
-                    featureEdit.addParameterEdit(parameter.getKey(), new MParameterEdit(FeatureWarningOnPortal.this, parameter, rootConfigPanel));
-                }
-                return featureEdit;
-            }
-        });
-        return "base." + getKey() ;
-    }
 }
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/cosmetics/FeatureNicknameColor.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/cosmetics/FeatureNicknameColor.java
index ce4599f5..bbf0129e 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/cosmetics/FeatureNicknameColor.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/cosmetics/FeatureNicknameColor.java
@@ -18,20 +18,18 @@
 
 package kr.syeyoung.dungeonsguide.mod.features.impl.cosmetics;
 
-import kr.syeyoung.dungeonsguide.mod.config.guiconfig.ConfigPanelCreator;
-import kr.syeyoung.dungeonsguide.mod.config.guiconfig.RootConfigPanel;
-import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
 import kr.syeyoung.dungeonsguide.mod.features.SimpleFeature;
+import kr.syeyoung.dungeonsguide.mod.guiv2.Widget;
+import kr.syeyoung.dungeonsguide.mod.guiv2.elements.CompatLayer;
 
 public class FeatureNicknameColor extends SimpleFeature {
     public FeatureNicknameColor() {
         super("Cosmetics", "Nickname Color", "Click on Edit to choose nickname color cosmetic", "cosmetic.nickname");
-        addParameter("dummy", new FeatureParameter("dummy", "dummy", "dummy", "dummy", "string"));
     }
 
     @Override
-    public String getEditRoute(RootConfigPanel rootConfigPanel) {
-        ConfigPanelCreator.map.put("base." + getKey() , () -> new PrefixSelectorGUI("color", new String[] {
+    public Widget getConfigureWidget() {
+        return new CompatLayer( new PrefixSelectorGUI("color", new String[] {
                 "§9Party §8> §r§a[RANK§6+§a] %prefix%%name%§f: TEST",
                 "§2Guild > §r§a[RANK§6+§a] %prefix%%name% §3[Vet]§f: TEST",
                 "§dTo §r§r§a[RANK§r§6+§r§a] %prefix%%name%§r§7: §r§7TEST§r",
@@ -39,7 +37,6 @@ public class FeatureNicknameColor extends SimpleFeature {
                 "§r§b[RANK§c+§b] %prefix%%name%§f: TEST",
                 "§r§bCo-op > §r§a[RANK§6+§a] %prefix%%name%§f: §rTEST§r"
         }, a -> (a.replace("&", "§")+"Color "+(a.replace("&", "§").equals("§z") ? "(Rainbow on sba)" : ""))));
-        return "base." + getKey();
     }
 
     @Override
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/cosmetics/FeatureNicknamePrefix.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/cosmetics/FeatureNicknamePrefix.java
index 698eabb9..fde0a86b 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/cosmetics/FeatureNicknamePrefix.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/cosmetics/FeatureNicknamePrefix.java
@@ -18,20 +18,21 @@
 
 package kr.syeyoung.dungeonsguide.mod.features.impl.cosmetics;
 
-import kr.syeyoung.dungeonsguide.mod.config.guiconfig.ConfigPanelCreator;
-import kr.syeyoung.dungeonsguide.mod.config.guiconfig.RootConfigPanel;
+import kr.syeyoung.dungeonsguide.mod.config.types.TCString;
 import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
 import kr.syeyoung.dungeonsguide.mod.features.SimpleFeature;
+import kr.syeyoung.dungeonsguide.mod.guiv2.Widget;
+import kr.syeyoung.dungeonsguide.mod.guiv2.elements.CompatLayer;
 
 public class FeatureNicknamePrefix extends SimpleFeature {
     public FeatureNicknamePrefix() {
         super("Cosmetics", "Nickname Prefix", "Click on Edit to choose prefix cosmetic", "cosmetic.prefix");
-        addParameter("dummy", new FeatureParameter("dummy", "dummy", "dummy", "dummy", "string"));
+        addParameter("dummy", new FeatureParameter("dummy", "dummy", "dummy", "dummy", TCString.INSTANCE));
     }
 
     @Override
-    public String getEditRoute(RootConfigPanel rootConfigPanel) {
-        ConfigPanelCreator.map.put("base." + getKey() , () -> new PrefixSelectorGUI("prefix", new String[] {
+    public Widget getConfigureWidget() {
+        return new CompatLayer(new PrefixSelectorGUI("prefix", new String[] {
                 "§9Party §8> §r%prefix% §a[RANK§6+§a] %name%§f: TEST",
                 "§2Guild > §r%prefix% §a[RANK§6+§a] %name% §3[Vet]§f: TEST",
                 "§dTo §r%prefix% §r§a[RANK§r§6+§r§a] %name%§r§7: §r§7TEST§r",
@@ -39,7 +40,6 @@ public class FeatureNicknamePrefix extends SimpleFeature {
                 "§r%prefix% §b[RANK§c+§b] %name%§f: TEST",
                 "§r§bCo-op > §r%prefix% §a[RANK§6+§a] %name%§f: §rTEST§r"
         }, a->a.replace("&", "§")));
-        return "base." + getKey();
     }
 
     @Override
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/inviteViewer/PartyInviteViewer.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/inviteViewer/PartyInviteViewer.java
index ae3f52e8..de4b390b 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/inviteViewer/PartyInviteViewer.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/inviteViewer/PartyInviteViewer.java
@@ -21,17 +21,16 @@ package kr.syeyoung.dungeonsguide.mod.features.impl.discord.inviteViewer;
 
 import kr.syeyoung.dungeonsguide.mod.DungeonsGuide;
 import kr.syeyoung.dungeonsguide.mod.SkyblockStatus;
+import kr.syeyoung.dungeonsguide.mod.config.types.TCInteger;
 import kr.syeyoung.dungeonsguide.mod.events.annotations.DGEventHandler;
 import kr.syeyoung.dungeonsguide.mod.events.impl.DGTickEvent;
 import kr.syeyoung.dungeonsguide.mod.events.impl.DiscordUserInvitedEvent;
 import kr.syeyoung.dungeonsguide.mod.events.impl.DiscordUserJoinRequestEvent;
 import kr.syeyoung.dungeonsguide.mod.features.AbstractGuiFeature;
 import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
-import kr.syeyoung.dungeonsguide.mod.guiv2.primitive.Rect;
 import kr.syeyoung.dungeonsguide.mod.overlay.OverlayType;
 import kr.syeyoung.dungeonsguide.mod.overlay.OverlayWidget;
 import kr.syeyoung.dungeonsguide.mod.overlay.WholeScreenPositioner;
-import net.minecraft.client.Minecraft;
 
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
@@ -42,7 +41,7 @@ public class PartyInviteViewer extends AbstractGuiFeature {
     public PartyInviteViewer() {
         super("Discord", "Party Invite Viewer","Simply type /dg asktojoin or /dg atj to toggle whether ask-to-join would be presented as option on discord!\n\nRequires Discord RPC to be enabled", "discord.discord_party_invite_viewer");
 
-        addParameter("ttl", new FeatureParameter<Integer>("ttl", "Request Duration", "The duration after which the requests will be dismissed automatically. The value is in seconds.", 15, "integer"));
+        addParameter("ttl", new FeatureParameter<Integer>("ttl", "Request Duration", "The duration after which the requests will be dismissed automatically. The value is in seconds.", 15, TCInteger.INSTANCE));
     }
 
     @Override
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/onlinealarm/PlayingDGAlarm.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/onlinealarm/PlayingDGAlarm.java
index 20edfc77..66c530d3 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/onlinealarm/PlayingDGAlarm.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/discord/onlinealarm/PlayingDGAlarm.java
@@ -24,11 +24,9 @@ import kr.syeyoung.dungeonsguide.mod.events.annotations.DGEventHandler;
 import kr.syeyoung.dungeonsguide.mod.events.impl.DGTickEvent;
 import kr.syeyoung.dungeonsguide.mod.events.impl.DiscordUserUpdateEvent;
 import kr.syeyoung.dungeonsguide.mod.features.AbstractGuiFeature;
-import kr.syeyoung.dungeonsguide.mod.guiv2.primitive.Rect;
 import kr.syeyoung.dungeonsguide.mod.overlay.OverlayType;
 import kr.syeyoung.dungeonsguide.mod.overlay.OverlayWidget;
 import kr.syeyoung.dungeonsguide.mod.overlay.WholeScreenPositioner;
-import net.minecraft.client.Minecraft;
 
 public class PlayingDGAlarm extends AbstractGuiFeature {
     private WidgetOnlinePeopleViewer onlinePeopleViewer;
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureBoxBats.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureBoxBats.java
index 56e32138..d6ddcdba 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureBoxBats.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureBoxBats.java
@@ -22,6 +22,8 @@ import com.google.common.base.Predicate;
 import kr.syeyoung.dungeonsguide.mod.DungeonsGuide;
 import kr.syeyoung.dungeonsguide.mod.SkyblockStatus;
 import kr.syeyoung.dungeonsguide.mod.config.types.AColor;
+import kr.syeyoung.dungeonsguide.mod.config.types.TCAColor;
+import kr.syeyoung.dungeonsguide.mod.config.types.TCInteger;
 import kr.syeyoung.dungeonsguide.mod.events.annotations.DGEventHandler;
 import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
 import kr.syeyoung.dungeonsguide.mod.features.SimpleFeature;
@@ -38,8 +40,8 @@ import java.util.List;
 public class FeatureBoxBats extends SimpleFeature  {
     public FeatureBoxBats() {
         super("Dungeon.Mobs", "Box Bats", "Box bats in dungeons\nDoes not appear through walls", "dungeon.batbox", true);
-        addParameter("radius", new FeatureParameter<Integer>("radius", "Highlight Radius", "The maximum distance between player and bats to be boxed", 20, "integer"));
-        addParameter("color", new FeatureParameter<AColor>("color", "Highlight Color", "Highlight Color of Bats", new AColor(255,0,0,50), "acolor"));
+        addParameter("radius", new FeatureParameter<Integer>("radius", "Highlight Radius", "The maximum distance between player and bats to be boxed", 20, TCInteger.INSTANCE));
+        addParameter("color", new FeatureParameter<AColor>("color", "Highlight Color", "Highlight Color of Bats", new AColor(255,0,0,50), TCAColor.INSTANCE));
     }
 
 
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureBoxSkelemaster.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureBoxSkelemaster.java
index c705febc..fa3784c7 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureBoxSkelemaster.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureBoxSkelemaster.java
@@ -22,6 +22,8 @@ import com.google.common.base.Predicate;
 import kr.syeyoung.dungeonsguide.mod.DungeonsGuide;
 import kr.syeyoung.dungeonsguide.mod.SkyblockStatus;
 import kr.syeyoung.dungeonsguide.mod.config.types.AColor;
+import kr.syeyoung.dungeonsguide.mod.config.types.TCAColor;
+import kr.syeyoung.dungeonsguide.mod.config.types.TCInteger;
 import kr.syeyoung.dungeonsguide.mod.events.annotations.DGEventHandler;
 import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
 import kr.syeyoung.dungeonsguide.mod.features.SimpleFeature;
@@ -38,8 +40,8 @@ import java.util.List;
 public class FeatureBoxSkelemaster extends SimpleFeature  {
     public FeatureBoxSkelemaster() {
         super("Dungeon.Mobs", "Box Skeleton Masters", "Box skeleton masters in dungeons", "dungeon.skeletonmasterbox", true);
-        addParameter("radius", new FeatureParameter<Integer>("radius", "Highlight Radius", "The maximum distance between player and skeletonmaster to be boxed", 20, "integer"));
-        addParameter("color", new FeatureParameter<AColor>("color", "Highlight Color", "Highlight Color of Skeleton master", new AColor(255,0,0,50), "acolor"));
+        addParameter("radius", new FeatureParameter<Integer>("radius", "Highlight Radius", "The maximum distance between player and skeletonmaster to be boxed", 20, TCInteger.INSTANCE));
+        addParameter("color", new FeatureParameter<AColor>("color", "Highlight Color", "Highlight Color of Skeleton master", new AColor(255,0,0,50), TCAColor.INSTANCE));
     }
 
 
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureBoxStarMobs.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureBoxStarMobs.java
index 462489ff..38e85304 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureBoxStarMobs.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureBoxStarMobs.java
@@ -22,6 +22,8 @@ import com.google.common.base.Predicate;
 import kr.syeyoung.dungeonsguide.mod.DungeonsGuide;
 import kr.syeyoung.dungeonsguide.mod.SkyblockStatus;
 import kr.syeyoung.dungeonsguide.mod.config.types.AColor;
+import kr.syeyoung.dungeonsguide.mod.config.types.TCAColor;
+import kr.syeyoung.dungeonsguide.mod.config.types.TCInteger;
 import kr.syeyoung.dungeonsguide.mod.events.annotations.DGEventHandler;
 import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
 import kr.syeyoung.dungeonsguide.mod.features.SimpleFeature;
@@ -38,8 +40,8 @@ import java.util.List;
 public class FeatureBoxStarMobs extends SimpleFeature {
     public FeatureBoxStarMobs() {
         super("Dungeon.Mobs", "Box Starred mobs", "Box Starred mobs in dungeons", "dungeon.starmobbox", false);
-        addParameter("radius", new FeatureParameter<Integer>("radius", "Highlight Radius", "The maximum distance between player and starred mobs to be boxed", 20, "integer"));
-        addParameter("color", new FeatureParameter<AColor>("color", "Highlight Color", "Highlight Color of Starred mobs", new AColor(0,255,255,50), "acolor"));
+        addParameter("radius", new FeatureParameter<Integer>("radius", "Highlight Radius", "The maximum distance between player and starred mobs to be boxed", 20, TCInteger.INSTANCE));
+        addParameter("color", new FeatureParameter<AColor>("color", "Highlight Color", "Highlight Color of Starred mobs", new AColor(0,255,255,50), TCAColor.INSTANCE));
     }
 
 
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureDungeonMap.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureDungeonMap.java
index a087a15b..43763842 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureDungeonMap.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureDungeonMap.java
@@ -22,8 +22,7 @@ import com.google.common.collect.ComparisonChain;
 import com.google.common.collect.Ordering;
 import kr.syeyoung.dungeonsguide.mod.DungeonsGuide;
 import kr.syeyoung.dungeonsguide.mod.chat.ChatTransmitter;
-import kr.syeyoung.dungeonsguide.mod.config.types.AColor;
-import kr.syeyoung.dungeonsguide.mod.config.types.GUIPosition;
+import kr.syeyoung.dungeonsguide.mod.config.types.*;
 import kr.syeyoung.dungeonsguide.mod.dungeon.DungeonContext;
 import kr.syeyoung.dungeonsguide.mod.dungeon.map.DungeonRoomScaffoldParser;
 import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom;
@@ -33,7 +32,6 @@ import kr.syeyoung.dungeonsguide.mod.events.impl.DungeonEndedEvent;
 import kr.syeyoung.dungeonsguide.mod.events.impl.DungeonStartedEvent;
 import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
 import kr.syeyoung.dungeonsguide.mod.features.RawRenderingGuiFeature;
-import kr.syeyoung.dungeonsguide.mod.guiv2.primitive.Size;
 import kr.syeyoung.dungeonsguide.mod.parallelUniverse.tab.TabList;
 import kr.syeyoung.dungeonsguide.mod.parallelUniverse.tab.TabListEntry;
 import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils;
@@ -84,20 +82,20 @@ public class FeatureDungeonMap extends RawRenderingGuiFeature {
     public FeatureDungeonMap() {
         super("Dungeon", "Dungeon Map", "Display dungeon map!", "dungeon.map", true, 128, 128);
         this.setEnabled(false);
-        addParameter("scale", new FeatureParameter<>("scale", "Scale map", "Whether to scale map to fit screen", true, "boolean", nval -> shouldScale = nval));
-        addParameter("cacheMap", new FeatureParameter<>("cacheMap", "Should cache map data", "name", true, "boolean", nval -> shouldCacheMap = nval));
-        addParameter("playerCenter", new FeatureParameter<>("playerCenter", "Center map at player", "Render you in the center", false, "boolean", nval -> centerMapOnPlayer = nval));
-        addParameter("rotate", new FeatureParameter<>("rotate", "Rotate map centered at player", "Only works with Center map at player enabled", false, "boolean", nval -> shouldRotateWithPlayer = nval));
-        addParameter("postScale", new FeatureParameter<>("postScale", "Scale factor of map", "Only works with Center map at player enabled", 1.0f, "float", nval -> postscaleOfMap = nval));
-        addParameter("useplayerheads", new FeatureParameter<>("useplayerheads", "Use player heads instead of arrows", "Option to use player heads instead of arrows", true, "boolean", nval -> showPlayerHeads = nval));
-        addParameter("showotherplayers", new FeatureParameter<>("showotherplayers", "Show other players", "Option to show other players in map", true, "boolean", nval -> shouldShowOtherPlayers = nval));
-        addParameter("showtotalsecrets", new FeatureParameter<>("showtotalsecrets", "Show Total secrets in the room", "Option to overlay total secrets in the specific room", true, "boolean", nval -> showSecretCount = nval));
-        addParameter("playerheadscale", new FeatureParameter<>("playerheadscale", "Player head scale", "Scale factor of player heads, defaults to 1", 1.0f, "float", nval -> playerHeadScale = nval));
-        addParameter("textScale", new FeatureParameter<>("textScale", "Text scale", "Scale factor of texts on map, defaults to 1", 1.0f, "float", nval -> textScale = nval));
-
-        addParameter("border_color", new FeatureParameter<>("border_color", "Color of the border", "Same as name", new AColor(255, 255, 255, 255), "acolor"));
-        addParameter("background_color", new FeatureParameter<>("background_color", "Color of the background", "Same as name", new AColor(0x22000000, true), "acolor", nval -> backgroudColor = nval));
-        addParameter("player_color", new FeatureParameter<>("player_color", "Color of the player border", "Same as name", new AColor(255, 255, 255, 0), "acolor", nval -> playerColor = nval));
+        addParameter("scale", new FeatureParameter<>("scale", "Scale map", "Whether to scale map to fit screen", true, TCBoolean.INSTANCE, nval -> shouldScale = nval));
+        addParameter("cacheMap", new FeatureParameter<>("cacheMap", "Should cache map data", "name", true, TCBoolean.INSTANCE, nval -> shouldCacheMap = nval));
+        addParameter("playerCenter", new FeatureParameter<>("playerCenter", "Center map at player", "Render you in the center", false, TCBoolean.INSTANCE, nval -> centerMapOnPlayer = nval));
+        addParameter("rotate", new FeatureParameter<>("rotate", "Rotate map centered at player", "Only works with Center map at player enabled", false, TCBoolean.INSTANCE, nval -> shouldRotateWithPlayer = nval));
+        addParameter("postScale", new FeatureParameter<>("postScale", "Scale factor of map", "Only works with Center map at player enabled", 1.0f, TCFloat.INSTANCE, nval -> postscaleOfMap = nval));
+        addParameter("useplayerheads", new FeatureParameter<>("useplayerheads", "Use player heads instead of arrows", "Option to use player heads instead of arrows", true, TCBoolean.INSTANCE, nval -> showPlayerHeads = nval));
+        addParameter("showotherplayers", new FeatureParameter<>("showotherplayers", "Show other players", "Option to show other players in map", true, TCBoolean.INSTANCE, nval -> shouldShowOtherPlayers = nval));
+        addParameter("showtotalsecrets", new FeatureParameter<>("showtotalsecrets", "Show Total secrets in the room", "Option to overlay total secrets in the specific room", true, TCBoolean.INSTANCE, nval -> showSecretCount = nval));
+        addParameter("playerheadscale", new FeatureParameter<>("playerheadscale", "Player head scale", "Scale factor of player heads, defaults to 1", 1.0f, TCFloat.INSTANCE, nval -> playerHeadScale = nval));
+        addParameter("textScale", new FeatureParameter<>("textScale", "Text scale", "Scale factor of texts on map, defaults to 1", 1.0f, TCFloat.INSTANCE, nval -> textScale = nval));
+
+        addParameter("border_color", new FeatureParameter<>("border_color", "Color of the border", "Same as name", new AColor(255, 255, 255, 255), TCAColor.INSTANCE));
+        addParameter("background_color", new FeatureParameter<>("background_color", "Color of the background", "Same as name", new AColor(0x22000000, true), TCAColor.INSTANCE, nval -> backgroudColor = nval));
+        addParameter("player_color", new FeatureParameter<>("player_color", "Color of the player border", "Same as name", new AColor(255, 255, 255, 0), TCAColor.INSTANCE, nval -> playerColor = nval));
     }
 
     public static final Ordering<NetworkPlayerInfo> sorter = Ordering.from((compare1, compare2) -> {
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureDungeonScore.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureDungeonScore.java
index 0926bdb9..e5f6a581 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureDungeonScore.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureDungeonScore.java
@@ -22,6 +22,7 @@ package kr.syeyoung.dungeonsguide.mod.features.impl.dungeon;
 import kr.syeyoung.dungeonsguide.mod.DungeonsGuide;
 import kr.syeyoung.dungeonsguide.mod.SkyblockStatus;
 import kr.syeyoung.dungeonsguide.mod.config.types.AColor;
+import kr.syeyoung.dungeonsguide.mod.config.types.TCBoolean;
 import kr.syeyoung.dungeonsguide.mod.dungeon.DungeonContext;
 import kr.syeyoung.dungeonsguide.mod.dungeon.map.DungeonRoomScaffoldParser;
 import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom;
@@ -50,7 +51,7 @@ public class FeatureDungeonScore extends TextHUDFeature {
     public FeatureDungeonScore() {
         super("Dungeon.HUDs", "Display Current Score", "Calculate and Display current score\nThis data is from pure calculation and can be different from actual score.", "dungeon.stats.score");
         this.setEnabled(false);
-        addParameter("verbose", new FeatureParameter<Boolean>("verbose", "Show each score instead of sum", "Skill: 100 Explore: 58 S->S+(5 tombs) instead of Score: 305", true, "boolean"));
+        addParameter("verbose", new FeatureParameter<Boolean>("verbose", "Show each score instead of sum", "Skill: 100 Explore: 58 S->S+(5 tombs) instead of Score: 305", true, TCBoolean.INSTANCE));
 
         getStyles().add(new TextStyle("scorename", new AColor(0x00, 0xAA,0xAA,255), new AColor(0, 0,0,0), false));
         getStyles().add(new TextStyle("separator", new AColor(0x55, 0x55,0x55,255), new AColor(0, 0,0,0), false));
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeaturePressAnyKeyToCloseChest.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeaturePressAnyKeyToCloseChest.java
index 8dd96533..07a8213f 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeaturePressAnyKeyToCloseChest.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeaturePressAnyKeyToCloseChest.java
@@ -20,6 +20,7 @@ package kr.syeyoung.dungeonsguide.mod.features.impl.dungeon;
 
 
 import kr.syeyoung.dungeonsguide.mod.DungeonsGuide;
+import kr.syeyoung.dungeonsguide.mod.config.types.TCInteger;
 import kr.syeyoung.dungeonsguide.mod.events.annotations.DGEventHandler;
 import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
 import kr.syeyoung.dungeonsguide.mod.features.SimpleFeature;
@@ -35,7 +36,7 @@ import org.lwjgl.input.Mouse;
 public class FeaturePressAnyKeyToCloseChest extends SimpleFeature {
     public FeaturePressAnyKeyToCloseChest() {
         super("Dungeon", "Press Any Mouse Button or Key to close Secret Chest", "dungeon.presskeytoclose");
-        addParameter("threshold", new FeatureParameter<Integer>("threshold", "Price Threshold", "The maximum price of item for chest to be closed. Default 1m", 1000000, "integer"));
+        addParameter("threshold", new FeatureParameter<Integer>("threshold", "Price Threshold", "The maximum price of item for chest to be closed. Default 1m", 1000000, TCInteger.INSTANCE));
     }
 
     @DGEventHandler
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureWarnLowHealth.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureWarnLowHealth.java
index 3396b8dd..f3310ff3 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureWarnLowHealth.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureWarnLowHealth.java
@@ -22,6 +22,7 @@ package kr.syeyoung.dungeonsguide.mod.features.impl.dungeon;
 import kr.syeyoung.dungeonsguide.mod.DungeonsGuide;
 import kr.syeyoung.dungeonsguide.mod.SkyblockStatus;
 import kr.syeyoung.dungeonsguide.mod.config.types.AColor;
+import kr.syeyoung.dungeonsguide.mod.config.types.TCInteger;
 import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
 import kr.syeyoung.dungeonsguide.mod.features.text.StyledText;
 import kr.syeyoung.dungeonsguide.mod.features.text.TextHUDFeature;
@@ -39,7 +40,7 @@ import java.util.List;
 public class FeatureWarnLowHealth extends TextHUDFeature {
     public FeatureWarnLowHealth() {
         super("Dungeon.Teammates", "Low Health Warning", "Warn if someone is on low health", "dungeon.lowhealthwarn");
-        addParameter("threshold", new FeatureParameter<Integer>("threshold", "Health Threshold", "Health Threshold for this feature to be toggled. default to 500", 500, "integer"));
+        addParameter("threshold", new FeatureParameter<Integer>("threshold", "Health Threshold", "Health Threshold for this feature to be toggled. default to 500", 500, TCInteger.INSTANCE));
         getStyles().add(new TextStyle("title", new AColor(0x00, 0xAA,0xAA,255), new AColor(0, 0,0,0), false));
         getStyles().add(new TextStyle("separator", new AColor(0x55, 0x55,0x55,255), new AColor(0, 0,0,0), false));
         getStyles().add(new TextStyle("number", new AColor(0xFF, 0x55,0x55,255), new AColor(0, 0,0,0), false));
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/etc/FeatureDecreaseExplosionSound.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/etc/FeatureDecreaseExplosionSound.java
index 3112a703..5f7d17dd 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/etc/FeatureDecreaseExplosionSound.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/etc/FeatureDecreaseExplosionSound.java
@@ -20,6 +20,7 @@ package kr.syeyoung.dungeonsguide.mod.features.impl.etc;
 
 
 import kr.syeyoung.dungeonsguide.mod.SkyblockStatus;
+import kr.syeyoung.dungeonsguide.mod.config.types.TCFloat;
 import kr.syeyoung.dungeonsguide.mod.events.annotations.DGEventHandler;
 import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
 import kr.syeyoung.dungeonsguide.mod.features.SimpleFeature;
@@ -29,7 +30,7 @@ import net.minecraftforge.client.event.sound.PlaySoundEvent;
 public class FeatureDecreaseExplosionSound extends SimpleFeature {
     public FeatureDecreaseExplosionSound() {
        super("Misc", "Decrease Explosion sound effect", "Decreases volume of explosions while on skyblock", "qol.explosionsound");
-        addParameter("sound", new FeatureParameter<Float>("sound", "Sound Multiplier %", "The volume of explosion effect will be multiplied by this value. 0~100", 10.0f, "float"));
+        addParameter("sound", new FeatureParameter<Float>("sound", "Sound Multiplier %", "The volume of explosion effect will be multiplied by this value. 0~100", 10.0f, TCFloat.INSTANCE));
     }
 
     @DGEventHandler
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/etc/FeatureDisableMessage.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/etc/FeatureDisableMessage.java
index 48056824..c9bfe226 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/etc/FeatureDisableMessage.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/etc/FeatureDisableMessage.java
@@ -20,6 +20,7 @@ package kr.syeyoung.dungeonsguide.mod.features.impl.etc;
 
 
 import kr.syeyoung.dungeonsguide.mod.SkyblockStatus;
+import kr.syeyoung.dungeonsguide.mod.config.types.TCBoolean;
 import kr.syeyoung.dungeonsguide.mod.events.annotations.DGEventHandler;
 import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
 import kr.syeyoung.dungeonsguide.mod.features.SimpleFeature;
@@ -57,7 +58,7 @@ public class FeatureDisableMessage extends SimpleFeature {
     public FeatureDisableMessage() {
         super("Misc.Chat", "Disable ability messages", "Do not let ability messages show up in chatbox\nclick on Edit for more precise settings", "fixes.messagedisable", true);
         for (MessageData messageData : PRE_DEFINED) {
-            addParameter(messageData.key, new FeatureParameter<Boolean>(messageData.key, messageData.name, messageData.description, true, "boolean"));
+            addParameter(messageData.key, new FeatureParameter<Boolean>(messageData.key, messageData.name, messageData.description, true, TCBoolean.INSTANCE));
         }
     }
 
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/etc/FeatureEpicCountdown.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/etc/FeatureEpicCountdown.java
index 8ec39ca5..5baab534 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/etc/FeatureEpicCountdown.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/etc/FeatureEpicCountdown.java
@@ -19,6 +19,7 @@
 package kr.syeyoung.dungeonsguide.mod.features.impl.etc;
 
 import kr.syeyoung.dungeonsguide.mod.DungeonsGuide;
+import kr.syeyoung.dungeonsguide.mod.config.types.TCBoolean;
 import kr.syeyoung.dungeonsguide.mod.events.annotations.DGEventHandler;
 import kr.syeyoung.dungeonsguide.mod.events.impl.DGTickEvent;
 import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
@@ -46,8 +47,8 @@ public class FeatureEpicCountdown extends SimpleFeature {
 
     public FeatureEpicCountdown() {
         super("Dungeon.HUDs", "Epic Dungeon Start Countdown", "Shows a cool dungeon start instead of the chat messages", "etc.dungeoncountdown", true);
-        addParameter("cleanchat", new FeatureParameter<>("cleanchat", "Clean Dungeon Chat", "^^^", true, "boolean", nval -> cleanChat = nval));
-        addParameter("sounds", new FeatureParameter<>("sounds", "Countdown SFX", "^^^", true, "boolean", nval -> sfxenabled = nval));
+        addParameter("cleanchat", new FeatureParameter<>("cleanchat", "Clean Dungeon Chat", "^^^", true, TCBoolean.INSTANCE, nval -> cleanChat = nval));
+        addParameter("sounds", new FeatureParameter<>("sounds", "Countdown SFX", "^^^", true, TCBoolean.INSTANCE, nval -> sfxenabled = nval));
 
         lastSec = GO_TEXT;
     }
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/etc/FeatureRepartyCommand.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/etc/FeatureRepartyCommand.java
index 0392d663..f7710b42 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/etc/FeatureRepartyCommand.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/etc/FeatureRepartyCommand.java
@@ -18,12 +18,13 @@
 
 package kr.syeyoung.dungeonsguide.mod.features.impl.etc;
 
+import kr.syeyoung.dungeonsguide.mod.config.types.TCString;
 import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
 import kr.syeyoung.dungeonsguide.mod.features.SimpleFeature;
 
 public class FeatureRepartyCommand extends SimpleFeature {
     public FeatureRepartyCommand() {
        super("Party.Reparty", "Enable Reparty Command From DG", "if you disable, /dg reparty will still work, Auto reparty will still work\nRequires Restart to get applied", "qol.reparty");
-        addParameter("command", new FeatureParameter<String>("command", "The Command", "Command that the reparty will be bound to", "reparty", "string"));
+        addParameter("command", new FeatureParameter<String>("command", "The Command", "Command that the reparty will be bound to", "reparty", TCString.INSTANCE));
     }
 }
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/etc/FeatureTooltipPrice.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/etc/FeatureTooltipPrice.java
index f34dbd6e..3effcd69 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/etc/FeatureTooltipPrice.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/etc/FeatureTooltipPrice.java
@@ -19,6 +19,7 @@
 package kr.syeyoung.dungeonsguide.mod.features.impl.etc;
 
 
+import kr.syeyoung.dungeonsguide.mod.config.types.TCBoolean;
 import kr.syeyoung.dungeonsguide.mod.events.annotations.DGEventHandler;
 import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
 import kr.syeyoung.dungeonsguide.mod.features.SimpleFeature;
@@ -36,7 +37,7 @@ import java.util.TreeSet;
 public class FeatureTooltipPrice extends SimpleFeature {
     public FeatureTooltipPrice() {
         super("Misc.API Features", "Item Price", "Shows price of items", "tooltip.price");
-        addParameter("reqShift", new FeatureParameter<Boolean>("reqShift", "Require Shift", "If shift needs to be pressed in order for this feature to be activated", false, "boolean"));
+        addParameter("reqShift", new FeatureParameter<Boolean>("reqShift", "Require Shift", "If shift needs to be pressed in order for this feature to be activated", false, TCBoolean.INSTANCE));
         setEnabled(false);
     }
 
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/etc/ability/FeatureAbilityCooldown.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/etc/ability/FeatureAbilityCooldown.java
index 68d4bf8b..32ba7920 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/etc/ability/FeatureAbilityCooldown.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/etc/ability/FeatureAbilityCooldown.java
@@ -21,6 +21,8 @@ package kr.syeyoung.dungeonsguide.mod.features.impl.etc.ability;
 
 import kr.syeyoung.dungeonsguide.mod.SkyblockStatus;
 import kr.syeyoung.dungeonsguide.mod.config.types.AColor;
+import kr.syeyoung.dungeonsguide.mod.config.types.TCBoolean;
+import kr.syeyoung.dungeonsguide.mod.config.types.TCInteger;
 import kr.syeyoung.dungeonsguide.mod.events.annotations.DGEventHandler;
 import kr.syeyoung.dungeonsguide.mod.events.impl.DGTickEvent;
 import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
@@ -48,8 +50,8 @@ public class FeatureAbilityCooldown extends TextHUDFeature {
         getStyles().add(new TextStyle("number", new AColor(0x55, 0xFF,0xFF,255), new AColor(0, 0,0,0), false));
         getStyles().add(new TextStyle("unit",new AColor(0x00, 0xAA,0xAA,255), new AColor(0, 0,0,0), false));
         getStyles().add(new TextStyle("ready",new AColor(0xDF, 0x00,0x67,255), new AColor(0, 0,0,0), false));
-        addParameter("disable", new FeatureParameter<Boolean>("disable", "Disable outside of dungeon", "Disable the feature when out of dungeon", false, "boolean"));
-        addParameter("decimal", new FeatureParameter<Integer>("decimal", "Decimal places", "ex) 2 -> Cooldown: 3.21 3-> Cooldown: 3.210", 0, "integer"));
+        addParameter("disable", new FeatureParameter<Boolean>("disable", "Disable outside of dungeon", "Disable the feature when out of dungeon", false, TCBoolean.INSTANCE));
+        addParameter("decimal", new FeatureParameter<Integer>("decimal", "Decimal places", "ex) 2 -> Cooldown: 3.21 3-> Cooldown: 3.210", 0, TCInteger.INSTANCE));
     }
 
     @Override
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/party/APIKey.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/party/APIKey.java
index 5db576be..9fec17be 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/party/APIKey.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/party/APIKey.java
@@ -20,6 +20,7 @@ package kr.syeyoung.dungeonsguide.mod.features.impl.party;
 
 
 import kr.syeyoung.dungeonsguide.mod.chat.ChatTransmitter;
+import kr.syeyoung.dungeonsguide.mod.config.types.TCString;
 import kr.syeyoung.dungeonsguide.mod.events.annotations.DGEventHandler;
 import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
 import kr.syeyoung.dungeonsguide.mod.features.SimpleFeature;
@@ -31,7 +32,7 @@ public class APIKey extends SimpleFeature {
 
     public APIKey() {
         super("Misc.API Features", "API KEY", "Sets api key","partykicker.apikey");
-        addParameter("apikey", new FeatureParameter<String>("apikey", "API Key", "API key", "","string"));
+        addParameter("apikey", new FeatureParameter<String>("apikey", "API Key", "API key", "", TCString.INSTANCE));
     }
 
     public String getAPIKey() {
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/party/customgui/PanelPartyFinder.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/party/customgui/PanelPartyFinder.java
index 0dc15904..b7ec2730 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/party/customgui/PanelPartyFinder.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/party/customgui/PanelPartyFinder.java
@@ -19,13 +19,17 @@
 package kr.syeyoung.dungeonsguide.mod.features.impl.party.customgui;
 
 
-import kr.syeyoung.dungeonsguide.mod.config.guiconfig.GuiConfigV2;
+import kr.syeyoung.dungeonsguide.mod.config.guiconfig.configv3.CategoryPageWidget;
+import kr.syeyoung.dungeonsguide.mod.config.guiconfig.configv3.MainConfigWidget;
 import kr.syeyoung.dungeonsguide.mod.discord.DiscordIntegrationManager;
 import kr.syeyoung.dungeonsguide.mod.events.impl.WindowUpdateEvent;
 import kr.syeyoung.dungeonsguide.mod.features.FeatureRegistry;
 import kr.syeyoung.dungeonsguide.mod.features.impl.discord.invteTooltip.MTooltipInvite;
 import kr.syeyoung.dungeonsguide.mod.gui.MPanel;
 import kr.syeyoung.dungeonsguide.mod.gui.elements.*;
+import kr.syeyoung.dungeonsguide.mod.guiv2.GuiScreenAdapter;
+import kr.syeyoung.dungeonsguide.mod.guiv2.elements.GlobalHUDScale;
+import kr.syeyoung.dungeonsguide.mod.guiv2.elements.Navigator;
 import kr.syeyoung.dungeonsguide.mod.party.PartyManager;
 import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils;
 import lombok.Getter;
@@ -111,9 +115,13 @@ public class PanelPartyFinder extends MPanel {
         settings.setBackground(RenderUtils.blendAlpha(0xFF141414, 0.05f));
         settings.setText("Settings");
         settings.setOnActionPerformed(() -> {
-            GuiConfigV2 guiConfigV2 = new GuiConfigV2();
-            guiConfigV2.getRootConfigPanel().setCurrentPageAndPushHistory("ROOT."+ FeatureRegistry.PARTYKICKER_CUSTOM.getCategory());
-            Minecraft.getMinecraft().displayGuiScreen(guiConfigV2);
+            MainConfigWidget mainConfigWidget = new MainConfigWidget();
+            GuiScreenAdapter adapter = new GuiScreenAdapter(new GlobalHUDScale(mainConfigWidget));
+            Minecraft.getMinecraft().displayGuiScreen(adapter);
+
+            Navigator.getNavigator(mainConfigWidget.getDomElement()).openPage(
+                    new CategoryPageWidget("Party")
+            );
         });
         discordInvite = new MButton();
         discordInvite.setText("Invite Discord Friends");
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/party/playerpreview/FeatureViewPlayerStatsOnJoin.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/party/playerpreview/FeatureViewPlayerStatsOnJoin.java
index f4ca5437..dbb14934 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/party/playerpreview/FeatureViewPlayerStatsOnJoin.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/party/playerpreview/FeatureViewPlayerStatsOnJoin.java
@@ -25,10 +25,7 @@ import io.github.moulberry.hychat.gui.GuiChatBox;
 import kr.syeyoung.dungeonsguide.mod.chat.ChatProcessResult;
 import kr.syeyoung.dungeonsguide.mod.chat.ChatProcessor;
 import kr.syeyoung.dungeonsguide.mod.chat.ChatTransmitter;
-import kr.syeyoung.dungeonsguide.mod.config.guiconfig.ConfigPanelCreator;
-import kr.syeyoung.dungeonsguide.mod.config.guiconfig.MFeatureEdit;
-import kr.syeyoung.dungeonsguide.mod.config.guiconfig.MParameterEdit;
-import kr.syeyoung.dungeonsguide.mod.config.guiconfig.RootConfigPanel;
+import kr.syeyoung.dungeonsguide.mod.config.types.TCStringList;
 import kr.syeyoung.dungeonsguide.mod.events.annotations.DGEventHandler;
 import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
 import kr.syeyoung.dungeonsguide.mod.features.FeatureRegistry;
@@ -36,8 +33,11 @@ import kr.syeyoung.dungeonsguide.mod.features.SimpleFeature;
 import kr.syeyoung.dungeonsguide.mod.features.impl.party.playerpreview.api.ApiFetcher;
 import kr.syeyoung.dungeonsguide.mod.features.impl.party.playerpreview.datarenders.DataRendererEditor;
 import kr.syeyoung.dungeonsguide.mod.features.impl.party.playerpreview.widget.WidgetProfileViewer;
-import kr.syeyoung.dungeonsguide.mod.guiv2.primitive.Rect;
-import kr.syeyoung.dungeonsguide.mod.overlay.*;
+import kr.syeyoung.dungeonsguide.mod.guiv2.elements.CompatLayer;
+import kr.syeyoung.dungeonsguide.mod.overlay.AbsPosPositioner;
+import kr.syeyoung.dungeonsguide.mod.overlay.OverlayManager;
+import kr.syeyoung.dungeonsguide.mod.overlay.OverlayType;
+import kr.syeyoung.dungeonsguide.mod.overlay.OverlayWidget;
 import kr.syeyoung.dungeonsguide.mod.party.PartyContext;
 import kr.syeyoung.dungeonsguide.mod.party.PartyManager;
 import kr.syeyoung.dungeonsguide.mod.utils.TextUtils;
@@ -72,7 +72,8 @@ public class FeatureViewPlayerStatsOnJoin extends SimpleFeature {
         super("Party", "View player stats when join", "view player rendering when joining/someone joins the party", "partykicker.viewstats", true);
         addParameter("datarenderers", new FeatureParameter<List<String>>("datarenderers", "DataRenderers", "Datarenderssdasd", new ArrayList<>(Arrays.asList(
                 "catalv", "selected_class_lv", "dungeon_catacombs_higheststat", "dungeon_master_catacombs_higheststat", "skill_combat_lv", "skill_foraging_lv", "skill_mining_lv", "fairysouls", "dummy"
-        )), "stringlist"));
+        )), TCStringList.INSTANCE)
+                .setWidgetGenerator(param -> new CompatLayer(new DataRendererEditor(FeatureViewPlayerStatsOnJoin.this))));
 
 
         ChatProcessor.INSTANCE.subscribe(((txt, messageContext) -> {
@@ -180,19 +181,4 @@ public class FeatureViewPlayerStatsOnJoin extends SimpleFeature {
         return ichatcomponent;
     }
 
-    @Override
-    public String getEditRoute(RootConfigPanel rootConfigPanel) {
-        ConfigPanelCreator.map.put("base." + getKey(), () -> {
-
-            MFeatureEdit featureEdit = new MFeatureEdit(FeatureViewPlayerStatsOnJoin.this, rootConfigPanel);
-            featureEdit.addParameterEdit("datarenderers", new DataRendererEditor(FeatureViewPlayerStatsOnJoin.this));
-            for (FeatureParameter parameter : getParameters()) {
-                if (parameter.getKey().equals("datarenderers")) continue;
-                featureEdit.addParameterEdit(parameter.getKey(), new MParameterEdit(FeatureViewPlayerStatsOnJoin.this, parameter, rootConfigPanel));
-            }
-            return featureEdit;
-        });
-        return "base." + getKey();
-    }
-
 }
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/party/playerpreview/api/SkinFetcher.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/party/playerpreview/api/SkinFetcher.java
index fa9e11ab..bf8ec262 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/party/playerpreview/api/SkinFetcher.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/party/playerpreview/api/SkinFetcher.java
@@ -20,7 +20,6 @@ package kr.syeyoung.dungeonsguide.mod.features.impl.party.playerpreview.api;
 
 import com.mojang.authlib.GameProfile;
 import com.mojang.authlib.minecraft.MinecraftProfileTexture;
-import kr.syeyoung.dungeonsguide.mod.features.impl.party.playerpreview.api.playerprofile.PlayerProfileParser;
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/party/playerpreview/widget/WidgetProfileViewer.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/party/playerpreview/widget/WidgetProfileViewer.java
index 018d77f1..71486ce6 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/party/playerpreview/widget/WidgetProfileViewer.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/party/playerpreview/widget/WidgetProfileViewer.java
@@ -27,8 +27,6 @@ import kr.syeyoung.dungeonsguide.mod.guiv2.xml.annotations.Bind;
 import kr.syeyoung.dungeonsguide.mod.guiv2.xml.annotations.On;
 import net.minecraft.util.ResourceLocation;
 
-import java.util.UUID;
-
 public class WidgetProfileViewer extends AnnotatedWidget {
 
     @Bind(variableName = "width")
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/party/playerpreview/widget/WidgetProfileViewerData.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/party/playerpreview/widget/WidgetProfileViewerData.java
index 13f9676f..998b6e42 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/party/playerpreview/widget/WidgetProfileViewerData.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/party/playerpreview/widget/WidgetProfileViewerData.java
@@ -29,14 +29,11 @@ import kr.syeyoung.dungeonsguide.mod.guiv2.DomElement;
 import kr.syeyoung.dungeonsguide.mod.guiv2.Widget;
 import kr.syeyoung.dungeonsguide.mod.guiv2.elements.popups.AbsLocationPopup;
 import kr.syeyoung.dungeonsguide.mod.guiv2.elements.popups.PopupMgr;
-import kr.syeyoung.dungeonsguide.mod.guiv2.elements.Scaler;
 import kr.syeyoung.dungeonsguide.mod.guiv2.primitive.Rect;
 import kr.syeyoung.dungeonsguide.mod.guiv2.xml.AnnotatedWidget;
 import kr.syeyoung.dungeonsguide.mod.guiv2.xml.annotations.Bind;
 import kr.syeyoung.dungeonsguide.mod.guiv2.xml.annotations.On;
 import kr.syeyoung.dungeonsguide.mod.guiv2.xml.data.WidgetList;
-import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.ScaledResolution;
 import net.minecraft.util.ResourceLocation;
 
 import java.util.ArrayList;
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/secret/FeatureBloodRush.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/secret/FeatureBloodRush.java
index c9db77b0..a9336b85 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/secret/FeatureBloodRush.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/secret/FeatureBloodRush.java
@@ -20,6 +20,7 @@ package kr.syeyoung.dungeonsguide.mod.features.impl.secret;
 
 
 import kr.syeyoung.dungeonsguide.mod.chat.ChatTransmitter;
+import kr.syeyoung.dungeonsguide.mod.config.types.TCKeybind;
 import kr.syeyoung.dungeonsguide.mod.events.annotations.DGEventHandler;
 import kr.syeyoung.dungeonsguide.mod.events.impl.KeyBindPressedEvent;
 import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
@@ -31,7 +32,7 @@ import org.lwjgl.input.Keyboard;
 public class FeatureBloodRush extends SimpleFeature {
     public FeatureBloodRush() {
         super("Dungeon.Secrets.Blood Rush", "Blood Rush Mode", "Auto pathfind to witherdoors. \nCan be toggled with key set in settings", "secret.bloodrush", false);
-        addParameter("key", new FeatureParameter<Integer>("key", "Key", "Press to toggle Blood Rush", Keyboard.KEY_NONE, "keybind"));
+        addParameter("key", new FeatureParameter<Integer>("key", "Key", "Press to toggle Blood Rush", Keyboard.KEY_NONE, TCKeybind.INSTANCE));
     }
 
     @DGEventHandler
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/secret/FeatureCreateRefreshLine.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/secret/FeatureCreateRefreshLine.java
index 7c7cd31a..be05710b 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/secret/FeatureCreateRefreshLine.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/secret/FeatureCreateRefreshLine.java
@@ -18,14 +18,11 @@
 
 package kr.syeyoung.dungeonsguide.mod.features.impl.secret;
 
-import com.google.common.base.Supplier;
-import kr.syeyoung.dungeonsguide.mod.config.guiconfig.ConfigPanelCreator;
-import kr.syeyoung.dungeonsguide.mod.config.guiconfig.MFeatureEdit;
-import kr.syeyoung.dungeonsguide.mod.config.guiconfig.MParameterEdit;
-import kr.syeyoung.dungeonsguide.mod.config.guiconfig.RootConfigPanel;
+import kr.syeyoung.dungeonsguide.mod.config.types.TCBoolean;
+import kr.syeyoung.dungeonsguide.mod.config.types.TCInteger;
+import kr.syeyoung.dungeonsguide.mod.config.types.TCKeybind;
 import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
 import kr.syeyoung.dungeonsguide.mod.features.SimpleFeature;
-import kr.syeyoung.dungeonsguide.mod.gui.MPanel;
 import org.lwjgl.input.Keyboard;
 
 import java.util.LinkedHashMap;
@@ -34,9 +31,9 @@ public class FeatureCreateRefreshLine extends SimpleFeature {
     public FeatureCreateRefreshLine() {
         super("Dungeon.Secrets.Keybinds", "Refresh pathfind line or Trigger pathfind", "A keybind for creating or refresh pathfind lines for pathfind contexts that doesn't have line, or contexts that has refresh rate set to -1.\nPress settings to edit the key", "secret.refreshPathfind", true);
         this.parameters = new LinkedHashMap<>();
-        addParameter("key", new FeatureParameter<Integer>("key", "Key","Press to refresh or create pathfind line", Keyboard.KEY_NONE, "keybind"));
-        addParameter("pathfind", new FeatureParameter<Boolean>("pathfind", "Enable Pathfinding", "Force Enable pathfind for future actions when used", false, "boolean"));
-        addParameter("refreshrate", new FeatureParameter<Integer>("refreshrate", "Line Refreshrate", "Ticks to wait per line refresh, to be overriden. If the line already has pathfind enabled, this value does nothing. Specify it to -1 to don't refresh line at all", 10, "integer"));
+        addParameter("key", new FeatureParameter<Integer>("key", "Key","Press to refresh or create pathfind line", Keyboard.KEY_NONE, TCKeybind.INSTANCE));
+        addParameter("pathfind", new FeatureParameter<Boolean>("pathfind", "Enable Pathfinding", "Force Enable pathfind for future actions when used", false, TCBoolean.INSTANCE));
+        addParameter("refreshrate", new FeatureParameter<Integer>("refreshrate", "Line Refreshrate", "Ticks to wait per line refresh, to be overriden. If the line already has pathfind enabled, this value does nothing. Specify it to -1 to don't refresh line at all", 10, TCInteger.INSTANCE));
     }
     public int getKeybind() {return this.<Integer>getParameter("key").getValue();}
     public boolean isPathfind() {
@@ -47,23 +44,4 @@ public class FeatureCreateRefreshLine extends SimpleFeature {
     }
 
 
-    public String getEditRoute(RootConfigPanel rootConfigPanel) {
-        ConfigPanelCreator.map.put("base." + getKey() , new Supplier<MPanel>() {
-            @Override
-            public MPanel get() {
-                MFeatureEdit featureEdit = new MFeatureEdit(FeatureCreateRefreshLine.this, rootConfigPanel);
-                for (FeatureParameter parameter: getParameters()) {
-                    if (parameter.getKey().equals("refreshrate"))
-                        featureEdit.addParameterEdit(parameter.getKey(), new MParameterEdit(FeatureCreateRefreshLine.this, parameter, rootConfigPanel, a -> !isPathfind()));
-                    else
-                        featureEdit.addParameterEdit(parameter.getKey(), new MParameterEdit(FeatureCreateRefreshLine.this, parameter, rootConfigPanel, a -> false));
-                }
-                return featureEdit;
-            }
-        });
-        return "base." + getKey() ;
-    }
-
-
-
 }
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/secret/FeatureFreezePathfind.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/secret/FeatureFreezePathfind.java
index 71ce11f4..6debe299 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/secret/FeatureFreezePathfind.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/secret/FeatureFreezePathfind.java
@@ -19,6 +19,7 @@
 package kr.syeyoung.dungeonsguide.mod.features.impl.secret;
 
 import kr.syeyoung.dungeonsguide.mod.chat.ChatTransmitter;
+import kr.syeyoung.dungeonsguide.mod.config.types.TCKeybind;
 import kr.syeyoung.dungeonsguide.mod.events.annotations.DGEventHandler;
 import kr.syeyoung.dungeonsguide.mod.events.impl.KeyBindPressedEvent;
 import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
@@ -30,7 +31,7 @@ import org.lwjgl.input.Keyboard;
 public class FeatureFreezePathfind extends SimpleFeature  {
     public FeatureFreezePathfind() {
         super("Dungeon.Secrets.Keybinds", "Global Freeze Pathfind", "Freeze Pathfind, meaning the pathfind lines won't change when you move.\nPress settings to edit the key", "secret.freezepathfind", false);
-        addParameter("key", new FeatureParameter<Integer>("key", "Key", "Press to toggle freeze pathfind", Keyboard.KEY_NONE, "keybind"));
+        addParameter("key", new FeatureParameter<Integer>("key", "Key", "Press to toggle freeze pathfind", Keyboard.KEY_NONE, TCKeybind.INSTANCE));
     }
 
     @DGEventHandler
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/secret/FeaturePathfindStrategy.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/secret/FeaturePathfindStrategy.java
index 406170ec..f1d23150 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/secret/FeaturePathfindStrategy.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/secret/FeaturePathfindStrategy.java
@@ -18,28 +18,18 @@
 
 package kr.syeyoung.dungeonsguide.mod.features.impl.secret;
 
-import com.google.common.base.Supplier;
-import com.google.gson.JsonObject;
-import kr.syeyoung.dungeonsguide.mod.config.guiconfig.ConfigPanelCreator;
-import kr.syeyoung.dungeonsguide.mod.config.guiconfig.MFeatureEdit;
-import kr.syeyoung.dungeonsguide.mod.config.guiconfig.MParameterEdit;
-import kr.syeyoung.dungeonsguide.mod.config.guiconfig.RootConfigPanel;
+import kr.syeyoung.dungeonsguide.mod.config.types.TCEnum;
 import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
 import kr.syeyoung.dungeonsguide.mod.features.SimpleFeature;
-import kr.syeyoung.dungeonsguide.mod.gui.MPanel;
-import kr.syeyoung.dungeonsguide.mod.gui.elements.MStringSelectionButton;
 import lombok.Getter;
 import lombok.RequiredArgsConstructor;
 
-import java.awt.*;
-import java.util.Arrays;
-import java.util.stream.Collectors;
-
 public class FeaturePathfindStrategy extends SimpleFeature {
     public FeaturePathfindStrategy() {
         super("Dungeon.Secrets.Preferences", "Pathfind Algorithm", "Select pathfind algorithm used by paths", "secret.secretpathfind.algorithm", true);
-        addParameter("strategy", new FeatureParameter<String>("strategy", "Pathfind Strategy", "Pathfind Strategy", "THETA_STAR", "string"));
-
+        addParameter("strategy", new FeatureParameter<PathfindStrategy>("strategy", "Pathfind Strategy", "Pathfind Strategy", PathfindStrategy.THETA_STAR, new TCEnum<>(PathfindStrategy.values()), neu -> {
+            if (this.parameters.containsKey("strategy")) this.<PathfindStrategy>getParameter("strategy").setDescription(neu.getDescription());
+        }));
     }
 
     @Override
@@ -47,37 +37,6 @@ public class FeaturePathfindStrategy extends SimpleFeature {
         return false;
     }
 
-    @Override
-    public String getEditRoute(RootConfigPanel rootConfigPanel) {
-        ConfigPanelCreator.map.put("base." + getKey() , new Supplier<MPanel>() {
-            @Override
-            public MPanel get() {
-
-                MFeatureEdit featureEdit = new MFeatureEdit(FeaturePathfindStrategy.this, rootConfigPanel);
-                PathfindStrategy alignment = getPathfindStrat();
-                MStringSelectionButton mStringSelectionButton = new MStringSelectionButton(Arrays.stream(PathfindStrategy.values()).map(Enum::name).collect(Collectors.toList()), alignment.name()) {
-                    @Override
-                    public Dimension getPreferredSize() {
-                        return new Dimension(150, 20);
-                    }
-                };
-                mStringSelectionButton.setOnUpdate(() -> {
-                    FeaturePathfindStrategy.this.<String>getParameter("strategy").setValue(mStringSelectionButton.getSelected());
-                    FeaturePathfindStrategy.this.<String>getParameter("strategy").setDescription(getPathfindStrat().getDescription());
-                    featureEdit.removeParameterEdit(null);
-                });
-                featureEdit.addParameterEdit("strategy", new MParameterEdit(FeaturePathfindStrategy.this, FeaturePathfindStrategy.this.<String>getParameter("strategy"), rootConfigPanel, mStringSelectionButton, (a) -> false));
-
-                for (FeatureParameter parameter: getParameters()) {
-                    if (parameter.getKey().equals("strategy")) continue;
-                    featureEdit.addParameterEdit(parameter.getKey(), new MParameterEdit(FeaturePathfindStrategy.this, parameter, rootConfigPanel));
-                }
-                return featureEdit;
-            }
-        });
-        return "base." + getKey() ;
-    }
-
     @Getter @RequiredArgsConstructor
     public enum PathfindStrategy {
         THETA_STAR("The default pathfinding algorithm. It will generate sub-optimal path quickly."),
@@ -86,18 +45,7 @@ public class FeaturePathfindStrategy extends SimpleFeature {
         private final String description;
     }
 
-    @Override
-    public void loadConfig(JsonObject jsonObject) {
-        super.loadConfig(jsonObject);
-        FeaturePathfindStrategy.PathfindStrategy alignment;
-        try {
-            alignment = PathfindStrategy.valueOf(FeaturePathfindStrategy.this.<String>getParameter("strategy").getValue());
-        } catch (Exception e) {alignment = PathfindStrategy.THETA_STAR;}
-        FeaturePathfindStrategy.this.<String>getParameter("strategy").setValue(alignment.name());
-        FeaturePathfindStrategy.this.<String>getParameter("strategy").setDescription(alignment.getDescription());
-    }
-
     public PathfindStrategy getPathfindStrat() {
-        return PathfindStrategy.valueOf(FeaturePathfindStrategy.this.<String>getParameter("strategy").getValue());
+        return FeaturePathfindStrategy.this.<PathfindStrategy>getParameter("strategy").getValue();
     }
 }
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/secret/FeaturePathfindToAll.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/secret/FeaturePathfindToAll.java
index 9435968f..e2781812 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/secret/FeaturePathfindToAll.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/secret/FeaturePathfindToAll.java
@@ -18,16 +18,17 @@
 
 package kr.syeyoung.dungeonsguide.mod.features.impl.secret;
 
+import kr.syeyoung.dungeonsguide.mod.config.types.TCBoolean;
 import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
 import kr.syeyoung.dungeonsguide.mod.features.SimpleFeature;
 
 public class FeaturePathfindToAll extends SimpleFeature {
     public FeaturePathfindToAll(){
         super("Dungeon.Secrets.Pathfind To All", "Start pathfind to all secrets upon entering a room", "Auto browse to all secrets in the room", "secret.secretpathfind.allbrowse", false);
-        addParameter("bat", new FeatureParameter<Boolean>("bat", "Trigger pathfind to Bat", "This feature will trigger pathfind to all bats in this room when entering a room", true, "boolean"));
-        addParameter("chest", new FeatureParameter<Boolean>("chest", "Trigger pathfind to Chest", "This feature will trigger pathfind to all chests in this room when entering a room", true, "boolean"));
-        addParameter("essence", new FeatureParameter<Boolean>("essence", "Trigger pathfind to Essence", "This feature will trigger pathfind to all essences in this room when entering a room", true, "boolean"));
-        addParameter("itemdrop", new FeatureParameter<Boolean>("itemdrop", "Trigger pathfind to Itemdrop", "This feature will trigger pathfind to all itemdrops in this room when entering a room", true, "boolean"));
+        addParameter("bat", new FeatureParameter<Boolean>("bat", "Trigger pathfind to Bat", "This feature will trigger pathfind to all bats in this room when entering a room", true, TCBoolean.INSTANCE));
+        addParameter("chest", new FeatureParameter<Boolean>("chest", "Trigger pathfind to Chest", "This feature will trigger pathfind to all chests in this room when entering a room", true, TCBoolean.INSTANCE));
+        addParameter("essence", new FeatureParameter<Boolean>("essence", "Trigger pathfind to Essence", "This feature will trigger pathfind to all essences in this room when entering a room", true, TCBoolean.INSTANCE));
+        addParameter("itemdrop", new FeatureParameter<Boolean>("itemdrop", "Trigger pathfind to Itemdrop", "This feature will trigger pathfind to all itemdrops in this room when entering a room", true, TCBoolean.INSTANCE));
     }
 
     public boolean isBat() {
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/secret/FeatureSoulRoomWarning.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/secret/FeatureSoulRoomWarning.java
index 3ccba58e..1496fa92 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/secret/FeatureSoulRoomWarning.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/secret/FeatureSoulRoomWarning.java
@@ -18,17 +18,13 @@
 
 package kr.syeyoung.dungeonsguide.mod.features.impl.secret;
 
-import com.google.common.base.Supplier;
 import kr.syeyoung.dungeonsguide.dungeon.data.DungeonRoomInfo;
 import kr.syeyoung.dungeonsguide.dungeon.mechanics.DungeonFairySoul;
 import kr.syeyoung.dungeonsguide.dungeon.mechanics.dunegonmechanic.DungeonMechanic;
 import kr.syeyoung.dungeonsguide.mod.DungeonsGuide;
 import kr.syeyoung.dungeonsguide.mod.SkyblockStatus;
-import kr.syeyoung.dungeonsguide.mod.config.guiconfig.ConfigPanelCreator;
-import kr.syeyoung.dungeonsguide.mod.config.guiconfig.MFeatureEdit;
-import kr.syeyoung.dungeonsguide.mod.config.guiconfig.MParameterEdit;
-import kr.syeyoung.dungeonsguide.mod.config.guiconfig.RootConfigPanel;
 import kr.syeyoung.dungeonsguide.mod.config.types.AColor;
+import kr.syeyoung.dungeonsguide.mod.config.types.TCStringList;
 import kr.syeyoung.dungeonsguide.mod.dungeon.DungeonContext;
 import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom;
 import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoomInfoRegistry;
@@ -37,24 +33,19 @@ import kr.syeyoung.dungeonsguide.mod.events.annotations.DGEventHandler;
 import kr.syeyoung.dungeonsguide.mod.events.impl.DGTickEvent;
 import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
 import kr.syeyoung.dungeonsguide.mod.features.text.*;
-import kr.syeyoung.dungeonsguide.mod.gui.MPanel;
-import kr.syeyoung.dungeonsguide.mod.gui.elements.MButton;
-import kr.syeyoung.dungeonsguide.mod.gui.elements.MPassiveLabelAndElement;
-import kr.syeyoung.dungeonsguide.mod.gui.elements.MStringSelectionButton;
-import kr.syeyoung.dungeonsguide.mod.gui.elements.MToggleButton;
-import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils;
+import kr.syeyoung.dungeonsguide.mod.guiv2.BindableAttribute;
+import kr.syeyoung.dungeonsguide.mod.guiv2.xml.AnnotatedImportOnlyWidget;
+import kr.syeyoung.dungeonsguide.mod.guiv2.xml.annotations.Bind;
+import kr.syeyoung.dungeonsguide.mod.guiv2.xml.annotations.On;
+import kr.syeyoung.dungeonsguide.mod.guiv2.xml.data.WidgetList;
 import net.minecraft.client.Minecraft;
+import net.minecraft.client.audio.PositionedSoundRecord;
 import net.minecraft.client.entity.EntityPlayerSP;
-import net.minecraft.client.gui.FontRenderer;
-import net.minecraft.client.gui.Gui;
-import net.minecraft.client.renderer.GlStateManager;
-import org.lwjgl.opengl.GL11;
-import org.lwjgl.opengl.GL14;
+import net.minecraft.util.ResourceLocation;
 
 import java.awt.*;
 import java.util.List;
 import java.util.*;
-import java.util.function.Predicate;
 
 public class FeatureSoulRoomWarning extends TextHUDFeature {
 
@@ -62,7 +53,8 @@ public class FeatureSoulRoomWarning extends TextHUDFeature {
         super("Dungeon.HUDs","Secret Soul Alert", "Alert if there is an fairy soul in the room", "secret.fairysoulwarn");
         getStyles().add(new TextStyle("warning", new AColor(0xFF, 0x69,0x17,255), new AColor(0, 0,0,0), false));
 
-        addParameter("roomuids", new FeatureParameter("roomuids", "Disabled room Names", "Disable for these rooms", new ArrayList<>(), "stringlist"));
+        addParameter("roomuids", new FeatureParameter<>("roomuids", "Disabled room Names", "Disable for these rooms", new ArrayList<>(), TCStringList.INSTANCE)
+                .setWidgetGenerator(RoomConfiguration::new));
     }
 
     SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus();
@@ -112,122 +104,80 @@ public class FeatureSoulRoomWarning extends TextHUDFeature {
         }
     }
 
-    @Override
-    public String getEditRoute(RootConfigPanel rootConfigPanel) {
-        ConfigPanelCreator.map.put("base." + getKey() , new Supplier<MPanel>() {
-            @Override
-            public MPanel get() {
-
-                MFeatureEdit featureEdit = new MFeatureEdit(FeatureSoulRoomWarning.this, rootConfigPanel);
-                featureEdit.addParameterEdit("textStyleNEW", new PanelTextParameterConfig(FeatureSoulRoomWarning.this));
-
-                StyledTextRenderer.Alignment alignment = StyledTextRenderer.Alignment.valueOf(FeatureSoulRoomWarning.this.<String>getParameter("alignment").getValue());
-                MStringSelectionButton mStringSelectionButton = new MStringSelectionButton(Arrays.asList("LEFT", "CENTER", "RIGHT"), alignment.name());
-                mStringSelectionButton.setOnUpdate(() -> {
-                    FeatureSoulRoomWarning.this.<String>getParameter("alignment").setValue(mStringSelectionButton.getSelected());
-                });
-                featureEdit.addParameterEdit("alignment", new MParameterEdit(FeatureSoulRoomWarning.this, FeatureSoulRoomWarning.this.<String>getParameter("alignment"), rootConfigPanel, mStringSelectionButton, (a) -> false));
+    public static class RoomConfiguration extends AnnotatedImportOnlyWidget {
 
-                for (FeatureParameter parameter: getParameters()) {
-                    if (parameter.getKey().equals("textStylesNEW")) continue;
-                    if (parameter.getKey().equals("alignment")) continue;
-                    if (parameter.getKey().equals("roomuids")) continue;
-                    featureEdit.addParameterEdit(parameter.getKey(), new MParameterEdit(FeatureSoulRoomWarning.this, parameter, rootConfigPanel));
-                }
-                featureEdit.addParameterEdit("roomuids", new RoomSelectionPanel(FeatureSoulRoomWarning.this.<List<String>>getParameter("roomuids"), (a) -> {
-                    for (DungeonMechanic value : a.getMechanics().values()) {
-                        if (value instanceof DungeonFairySoul) return true;
-                    }
-                    return false;
-                }) );
-                return featureEdit;
-            }
-        });
-        return "base." + getKey() ;
-    }
+        @Bind(
+                variableName = "rooms"
+        )
+        public final BindableAttribute rooms = new BindableAttribute(WidgetList.class);
+
+        public final Map<String, BindableAttribute<Boolean>> ifOrnot = new HashMap<>();
 
-    public static class RoomSelectionPanel extends MPanel {
         FeatureParameter<List<String>> uids;
-        private List<MPassiveLabelAndElement> passiveLabelAndElements = new ArrayList<>();
-        private List<MToggleButton> toggleButtons = new ArrayList<>();
-        private MButton addAll, removeAll;
-        public RoomSelectionPanel(FeatureParameter<List<String>> roomuids, Predicate<DungeonRoomInfo> selectableRooms) {
-            this.uids = roomuids;
-            for (DungeonRoomInfo dungeonRoomInfo : DungeonRoomInfoRegistry.getRegistered()) {
-                if (!selectableRooms.test(dungeonRoomInfo)) continue;
-                MToggleButton mToggleButton = new MToggleButton();
-                mToggleButton.setEnabled(!roomuids.getValue().contains(dungeonRoomInfo.getUuid().toString()));
-                mToggleButton.setOnToggle(() -> {
-                    if (mToggleButton.isEnabled())
-                        roomuids.getValue().remove(dungeonRoomInfo.getUuid().toString());
-                    else
-                        roomuids.getValue().add(dungeonRoomInfo.getUuid().toString());
-                });
-                toggleButtons.add(mToggleButton);
-                MPassiveLabelAndElement passiveLabelAndElement = new MPassiveLabelAndElement(dungeonRoomInfo.getName(), mToggleButton);
-                passiveLabelAndElement.setDivideRatio(0.7);
-                passiveLabelAndElements.add(passiveLabelAndElement);
-            }
-            for (MPassiveLabelAndElement passiveLabelAndElement : passiveLabelAndElements) {
-                add(passiveLabelAndElement);
+        private List<RoomSwitch> switches;
+        public RoomConfiguration(FeatureParameter<List<String>> uids) {
+            super(new ResourceLocation("dungeonsguide:gui/features/fairysoul/roomconfiguration.gui"));
+
+            for (String s : uids.getValue()) {
+                ifOrnot.put(s, new BindableAttribute<>(Boolean.class, true));
             }
-            {
-                addAll = new MButton(); addAll.setText("Enable All");
-                addAll.setOnActionPerformed(() -> {
-                    roomuids.getValue().clear();
-                    for (MToggleButton toggleButton : toggleButtons) {
-                        toggleButton.setEnabled(true);
-                    }
-                });
-                removeAll = new MButton(); removeAll.setText("Disable All");
-                removeAll.setOnActionPerformed(() -> {
-                    for (MToggleButton toggleButton : toggleButtons) {
-                        toggleButton.setEnabled(false);
-                        toggleButton.getOnToggle().run();
-                    }
+
+            rooms.setValue(switches = buildRooms());
+
+            for (Map.Entry<String, BindableAttribute<Boolean>> value : ifOrnot.entrySet()) {
+                value.getValue().addOnUpdate((old, neu) -> {
+                    Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F));
+                    if (neu) uids.getValue().add(value.getKey());
+                    else uids.getValue().remove(value.getKey());
                 });
-                add(addAll); add(removeAll);
             }
         }
 
-        @Override
-        public Dimension getPreferredSize() {
-            return new Dimension(-1, (int) (20 * Math.ceil(passiveLabelAndElements.size() / 3) + 27));
-        }
-
-        @Override
-        public void onBoundsUpdate() {
-            int xI = 0;
-            int y = 22;
-            int w3 = (getBounds().width-20) / 3;
-            for (MPassiveLabelAndElement passiveLabelAndElement : passiveLabelAndElements) {
-                passiveLabelAndElement.setBounds(new Rectangle(5 + xI * (w3+5), y, w3, 20));
-                xI ++;
-                if (xI == 3) {
-                    xI = 0;
-                    y += 20;
+        public List<RoomSwitch> buildRooms() {
+            List<RoomSwitch> switches1 = new LinkedList<>();
+            for (DungeonRoomInfo dungeonRoomInfo : DungeonRoomInfoRegistry.getRegistered()) {
+                boolean found = false;
+                for (DungeonMechanic value : dungeonRoomInfo.getMechanics().values()) {
+                    if (value instanceof DungeonFairySoul) {
+                        found = true;
+                        break;
+                    }
                 }
+                if (!found) continue;
+
+                if (!ifOrnot.containsKey(dungeonRoomInfo.getUuid().toString()))
+                    ifOrnot.put(dungeonRoomInfo.getUuid().toString(), new BindableAttribute<>(Boolean.class, false));
+                RoomSwitch roomSwitch = new RoomSwitch(dungeonRoomInfo, ifOrnot.get(dungeonRoomInfo.getUuid().toString()));
+                switches1.add(roomSwitch);
             }
+            return switches1;
+        }
 
-            addAll.setBounds(new Rectangle(getBounds().width-150, 2, 70, 14));
-            removeAll.setBounds(new Rectangle(getBounds().width-75, 2, 70, 14));
+        @On(functionName = "eall")
+        public void enableAll() {
+            Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F));
+            for (BindableAttribute<Boolean> value : ifOrnot.values()) {
+                value.setValue(true);
+            }
         }
+        @On(functionName = "dall")
+        public void disableAll() {
+            Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F));
+            for (BindableAttribute<Boolean> value : ifOrnot.values()) {
+                value.setValue(false);
+            }
+        }
+    }
 
-        @Override
-        public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) {
-            Gui.drawRect(0,0,getBounds().width, getBounds().height, RenderUtils.blendAlpha(0x141414, 0.12f));
-            Gui.drawRect(1,18,getBounds().width -1, getBounds().height-1, RenderUtils.blendAlpha(0x141414, 0.15f));
-            Gui.drawRect(1,1,getBounds().width-1, 18, RenderUtils.blendAlpha(0x141414, 0.12f));
-
-            FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
-            GlStateManager.pushMatrix();
-            GlStateManager.translate(5,5,0);
-            GlStateManager.scale(1.0,1.0,0);
-            GlStateManager.enableBlend();
-            GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
-            GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
-            fr.drawString("Enable for these rooms", 0,0, 0xFFFFFFFF);
-            GlStateManager.popMatrix();
+    public static class RoomSwitch extends AnnotatedImportOnlyWidget {
+        @Bind(variableName = "name")
+        public final BindableAttribute<String> name = new BindableAttribute<>(String.class);
+        @Bind(variableName = "enabled")
+        public final BindableAttribute<Boolean> enabled= new BindableAttribute<>(Boolean.class);
+        public RoomSwitch(DungeonRoomInfo dungeonRoomInfo, BindableAttribute<Boolean> linkTo) {
+            super(new ResourceLocation("dungeonsguide:gui/features/fairysoul/roomswitch.gui"));
+            name.setValue(dungeonRoomInfo.getName());
+            enabled.exportTo(linkTo);
         }
     }
 }
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/secret/FeatureTogglePathfind.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/secret/FeatureTogglePathfind.java
index f77da653..e3d97743 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/secret/FeatureTogglePathfind.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/secret/FeatureTogglePathfind.java
@@ -20,6 +20,7 @@ package kr.syeyoung.dungeonsguide.mod.features.impl.secret;
 
 
 import kr.syeyoung.dungeonsguide.mod.chat.ChatTransmitter;
+import kr.syeyoung.dungeonsguide.mod.config.types.TCKeybind;
 import kr.syeyoung.dungeonsguide.mod.events.annotations.DGEventHandler;
 import kr.syeyoung.dungeonsguide.mod.events.impl.KeyBindPressedEvent;
 import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
@@ -30,7 +31,7 @@ import org.lwjgl.input.Keyboard;
 public class FeatureTogglePathfind extends SimpleFeature {
     public FeatureTogglePathfind() {
         super("Dungeon.Secrets.Keybinds", "Toggle Pathfind Lines", "A key for toggling pathfound line visibility.\nPress settings to edit the key", "secret.togglePathfind");
-        addParameter("key", new FeatureParameter<Integer>("key", "Key", "Press to toggle pathfind lines", Keyboard.KEY_NONE, "keybind"));
+        addParameter("key", new FeatureParameter<Integer>("key", "Key", "Press to toggle pathfind lines", Keyboard.KEY_NONE, TCKeybind.INSTANCE));
     }
     public boolean togglePathfindStatus = false;
 
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/secret/PathfindLineProperties.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/secret/PathfindLineProperties.java
index f5137394..fd49c21d 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/secret/PathfindLineProperties.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/secret/PathfindLineProperties.java
@@ -18,16 +18,10 @@
 
 package kr.syeyoung.dungeonsguide.mod.features.impl.secret;
 
-import com.google.common.base.Supplier;
-import kr.syeyoung.dungeonsguide.mod.config.guiconfig.ConfigPanelCreator;
-import kr.syeyoung.dungeonsguide.mod.config.guiconfig.MFeatureEdit;
-import kr.syeyoung.dungeonsguide.mod.config.guiconfig.MParameterEdit;
-import kr.syeyoung.dungeonsguide.mod.config.guiconfig.RootConfigPanel;
-import kr.syeyoung.dungeonsguide.mod.config.types.AColor;
+import kr.syeyoung.dungeonsguide.mod.config.types.*;
 import kr.syeyoung.dungeonsguide.mod.dungeon.actions.tree.ActionRouteProperties;
 import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
 import kr.syeyoung.dungeonsguide.mod.features.SimpleFeature;
-import kr.syeyoung.dungeonsguide.mod.gui.MPanel;
 
 import java.util.LinkedHashMap;
 
@@ -38,38 +32,17 @@ public class PathfindLineProperties extends SimpleFeature {
         this.parent = parent;
         this.parameters = new LinkedHashMap<>();
         if (parent != null)
-            addParameter("useGlobal", new FeatureParameter<Boolean>("useGlobal", "Use Global Settings instead of this", "Completely ignore these settings, then use the parent one:: '"+parent.getName()+"'",  useParent, "boolean"));
-        addParameter("pathfind", new FeatureParameter<Boolean>("pathfind", "Enable Pathfinding", "Enable pathfind for secrets",  useParent, "boolean"));
-        addParameter("lineColor", new FeatureParameter<AColor>("lineColor", "Line Color", "Color of the pathfind line", new AColor(0xFFFF0000, true), "acolor"));
-        addParameter("lineWidth", new FeatureParameter<Float>("lineWidth", "Line Thickness", "Thickness of the pathfind line",1.0f, "float"));
-        addParameter("linerefreshrate", new FeatureParameter<Integer>("linerefreshrate", "Line Refreshrate", "Ticks to wait per line refresh. Specify it to -1 to don't refresh line at all", 10, "integer"));
-        addParameter("beacon", new FeatureParameter<Boolean>("beacon", "Enable Beacons", "Enable beacons for pathfind line targets",  true, "boolean"));
-        addParameter("beamColor", new FeatureParameter<AColor>("beamColor", "Beam Color", "Color of the beacon beam", new AColor(0x77FF0000, true), "acolor"));
-        addParameter("beamTargetColor", new FeatureParameter<AColor>("beamTargetColor", "Target Color", "Color of the target", new AColor(0x33FF0000, true), "acolor"));
+            addParameter("useGlobal", new FeatureParameter<Boolean>("useGlobal", "Use Global Settings instead of this", "Completely ignore these settings, then use the parent one:: '"+parent.getName()+"'",  useParent, TCBoolean.INSTANCE));
+        addParameter("pathfind", new FeatureParameter<Boolean>("pathfind", "Enable Pathfinding", "Enable pathfind for secrets",  useParent, TCBoolean.INSTANCE));
+        addParameter("lineColor", new FeatureParameter<AColor>("lineColor", "Line Color", "Color of the pathfind line", new AColor(0xFFFF0000, true), TCAColor.INSTANCE));
+        addParameter("lineWidth", new FeatureParameter<Float>("lineWidth", "Line Thickness", "Thickness of the pathfind line",1.0f, TCFloat.INSTANCE));
+        addParameter("linerefreshrate", new FeatureParameter<Integer>("linerefreshrate", "Line Refreshrate", "Ticks to wait per line refresh. Specify it to -1 to don't refresh line at all", 10, TCInteger.INSTANCE));
+        addParameter("beacon", new FeatureParameter<Boolean>("beacon", "Enable Beacons", "Enable beacons for pathfind line targets",  true, TCBoolean.INSTANCE));
+        addParameter("beamColor", new FeatureParameter<AColor>("beamColor", "Beam Color", "Color of the beacon beam", new AColor(0x77FF0000, true), TCAColor.INSTANCE));
+        addParameter("beamTargetColor", new FeatureParameter<AColor>("beamTargetColor", "Target Color", "Color of the target", new AColor(0x33FF0000, true), TCAColor.INSTANCE));
     }
 
 
-    public String getEditRoute(RootConfigPanel rootConfigPanel) {
-        ConfigPanelCreator.map.put("base." + getKey() , new Supplier<MPanel>() {
-            @Override
-            public MPanel get() {
-                MFeatureEdit featureEdit = new MFeatureEdit(PathfindLineProperties.this, rootConfigPanel);
-                for (FeatureParameter parameter: getParameters()) {
-                    if (parameter.getKey().startsWith("line"))
-                        featureEdit.addParameterEdit(parameter.getKey(), new MParameterEdit(PathfindLineProperties.this, parameter, rootConfigPanel, a -> isGlobal() || !isPathfind()));
-                    else if (parameter.getKey().startsWith("beam"))
-                        featureEdit.addParameterEdit(parameter.getKey(), new MParameterEdit(PathfindLineProperties.this, parameter, rootConfigPanel, a -> isGlobal() || !isBeacon()));
-                    else if (!parameter.getKey().equals("useGlobal"))
-                        featureEdit.addParameterEdit(parameter.getKey(), new MParameterEdit(PathfindLineProperties.this, parameter, rootConfigPanel, a -> isGlobal()));
-                    else
-                        featureEdit.addParameterEdit(parameter.getKey(), new MParameterEdit(PathfindLineProperties.this, parameter, rootConfigPanel, a -> false));
-                }
-                return featureEdit;
-            }
-        });
-        return "base." + getKey() ;
-    }
-
     @Override
     public boolean isDisyllable() {
         return false;
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/secret/mechanicbrowser/FeatureMechanicBrowse.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/secret/mechanicbrowser/FeatureMechanicBrowse.java
index 32f46f5b..3795e3b5 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/secret/mechanicbrowser/FeatureMechanicBrowse.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/secret/mechanicbrowser/FeatureMechanicBrowse.java
@@ -22,6 +22,7 @@ package kr.syeyoung.dungeonsguide.mod.features.impl.secret.mechanicbrowser;
 import kr.syeyoung.dungeonsguide.mod.DungeonsGuide;
 import kr.syeyoung.dungeonsguide.mod.SkyblockStatus;
 import kr.syeyoung.dungeonsguide.mod.config.types.GUIPosition;
+import kr.syeyoung.dungeonsguide.mod.config.types.TCFloat;
 import kr.syeyoung.dungeonsguide.mod.dungeon.DungeonContext;
 import kr.syeyoung.dungeonsguide.mod.dungeon.actions.tree.ActionRoute;
 import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom;
@@ -30,11 +31,7 @@ import kr.syeyoung.dungeonsguide.mod.events.annotations.DGEventHandler;
 import kr.syeyoung.dungeonsguide.mod.events.impl.DGTickEvent;
 import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
 import kr.syeyoung.dungeonsguide.mod.features.RawRenderingGuiFeature;
-import kr.syeyoung.dungeonsguide.mod.gui.MPanel;
-import kr.syeyoung.dungeonsguide.mod.gui.elements.MFloatSelectionButton;
-import kr.syeyoung.dungeonsguide.mod.gui.elements.MPassiveLabelAndElement;
 import kr.syeyoung.dungeonsguide.mod.guiv2.Widget;
-import kr.syeyoung.dungeonsguide.mod.guiv2.primitive.Size;
 import kr.syeyoung.dungeonsguide.mod.overlay.GUIRectPositioner;
 import kr.syeyoung.dungeonsguide.mod.overlay.OverlayManager;
 import kr.syeyoung.dungeonsguide.mod.overlay.OverlayType;
@@ -52,8 +49,10 @@ import org.lwjgl.opengl.GL11;
 import org.lwjgl.opengl.GL14;
 
 import java.awt.*;
-import java.util.*;
 import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.UUID;
 
 public class FeatureMechanicBrowse extends RawRenderingGuiFeature {
 
@@ -63,7 +62,7 @@ public class FeatureMechanicBrowse extends RawRenderingGuiFeature {
 
     public FeatureMechanicBrowse() {
         super("Dungeon.Secrets.Secret Browser","Secret Browser", "Browse and Pathfind secrets and mechanics in the current room", "secret.mechanicbrowse", false, 100, 300);
-        addParameter("scale", new FeatureParameter<Float>("scale", "Scale", "Scale", 1.0f, "float"));
+        addParameter("scale", new FeatureParameter<Float>("scale", "Scale", "Scale", 1.0f, TCFloat.INSTANCE));
     }
 
     public double getScale() {
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/solvers/FeatureSolverBlaze.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/solvers/FeatureSolverBlaze.java
index 9c1626a3..07376718 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/solvers/FeatureSolverBlaze.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/solvers/FeatureSolverBlaze.java
@@ -19,16 +19,17 @@
 package kr.syeyoung.dungeonsguide.mod.features.impl.solvers;
 
 import kr.syeyoung.dungeonsguide.mod.config.types.AColor;
+import kr.syeyoung.dungeonsguide.mod.config.types.TCAColor;
 import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
 import kr.syeyoung.dungeonsguide.mod.features.SimpleFeature;
 
 public class FeatureSolverBlaze extends SimpleFeature {
     public FeatureSolverBlaze() {
         super("Dungeon.Solvers.Floor 2+", "Blaze", "Highlights the blaze that needs to be killed in an blaze room", "solver.blaze");
-        addParameter("normBlazeColor", new FeatureParameter<AColor>("blazecolor", "Normal Blaze Color", "Normal Blaze Color", new AColor(255,255,255,255), "acolor", nval -> normBlazeColor = nval));
-        addParameter("nextBlazeColor", new FeatureParameter<AColor>("blazecolor", "Next Blaze Color", "Next Blaze Color", new AColor(0,255,0,255), "acolor", nval -> nextBlazeColor = nval));
-        addParameter("nextUpBlazeColor", new FeatureParameter<AColor>("blazecolor", "Next Up Blaze Color", "Color of blaze after next blaze", new AColor(255,255,0,255), "acolor", nval -> nextUpBlazeColor = nval));
-        addParameter("blazeborder", new FeatureParameter<AColor>("blazeborder", "Blaze Border Color", "Blaze border color", new AColor(255,255,255,0), "acolor", nval -> blazeBorder = nval));
+        addParameter("normBlazeColor", new FeatureParameter<AColor>("blazecolor", "Normal Blaze Color", "Normal Blaze Color", new AColor(255,255,255,255), TCAColor.INSTANCE, nval -> normBlazeColor = nval));
+        addParameter("nextBlazeColor", new FeatureParameter<AColor>("blazecolor", "Next Blaze Color", "Next Blaze Color", new AColor(0,255,0,255), TCAColor.INSTANCE, nval -> nextBlazeColor = nval));
+        addParameter("nextUpBlazeColor", new FeatureParameter<AColor>("blazecolor", "Next Up Blaze Color", "Color of blaze after next blaze", new AColor(255,255,0,255), TCAColor.INSTANCE, nval -> nextUpBlazeColor = nval));
+        addParameter("blazeborder", new FeatureParameter<AColor>("blazeborder", "Blaze Border Color", "Blaze border color", new AColor(255,255,255,0), TCAColor.INSTANCE, nval -> blazeBorder = nval));
     }
 
     AColor normBlazeColor;
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/solvers/FeatureSolverBombdefuse.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/solvers/FeatureSolverBombdefuse.java
index 1eb2c930..5242f18f 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/solvers/FeatureSolverBombdefuse.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/solvers/FeatureSolverBombdefuse.java
@@ -18,6 +18,7 @@
 
 package kr.syeyoung.dungeonsguide.mod.features.impl.solvers;
 
+import kr.syeyoung.dungeonsguide.mod.config.types.TCKeybind;
 import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
 import kr.syeyoung.dungeonsguide.mod.features.SimpleFeature;
 import org.lwjgl.input.Keyboard;
@@ -25,6 +26,6 @@ import org.lwjgl.input.Keyboard;
 public class FeatureSolverBombdefuse extends SimpleFeature {
     public FeatureSolverBombdefuse() {
         super("Dungeon.Solvers.Floor 7+", "Bomb Defuse", "Communicates with others dg using key 'F' for solutions and displays it",  "solver.bombdefuse");
-        addParameter("key", new FeatureParameter<Integer>("key", "Key","Press to send solution in chat", Keyboard.KEY_NONE, "keybind"));
+        addParameter("key", new FeatureParameter<Integer>("key", "Key","Press to send solution in chat", Keyboard.KEY_NONE, TCKeybind.INSTANCE));
     }
 }
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/solvers/FeatureSolverBox.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/solvers/FeatureSolverBox.java
index 0c00add5..f1e5bc98 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/solvers/FeatureSolverBox.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/solvers/FeatureSolverBox.java
@@ -19,6 +19,9 @@
 package kr.syeyoung.dungeonsguide.mod.features.impl.solvers;
 
 import kr.syeyoung.dungeonsguide.mod.config.types.AColor;
+import kr.syeyoung.dungeonsguide.mod.config.types.TCAColor;
+import kr.syeyoung.dungeonsguide.mod.config.types.TCBoolean;
+import kr.syeyoung.dungeonsguide.mod.config.types.TCFloat;
 import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
 import kr.syeyoung.dungeonsguide.mod.features.SimpleFeature;
 
@@ -28,13 +31,13 @@ public class FeatureSolverBox extends SimpleFeature {
     public FeatureSolverBox() {
         super("Dungeon.Solvers.Floor 3+", "Box (Advanced)", "Calculates solution for box puzzle room, and displays it to user",  "solver.box");
         this.parameters = new LinkedHashMap<>();
-        addParameter("disableText", new FeatureParameter<Boolean>("disableText", "Box Puzzle Solver Disable text", "Disable 'Type recalc to recalculate solution' showing up on top left.\nYou can still type recalc to recalc solution after disabling this feature", false, "boolean"));
-        addParameter("lineColor", new FeatureParameter<AColor>("lineColor", "Line Color", "Color of the solution line", new AColor(0xFF00FF00, true), "acolor"));
-        addParameter("lineWidth", new FeatureParameter<Float>("lineWidth", "Line Thickness", "Thickness of the solution line",1.0f, "float"));
+        addParameter("disableText", new FeatureParameter<Boolean>("disableText", "Box Puzzle Solver Disable text", "Disable 'Type recalc to recalculate solution' showing up on top left.\nYou can still type recalc to recalc solution after disabling this feature", false, TCBoolean.INSTANCE));
+        addParameter("lineColor", new FeatureParameter<AColor>("lineColor", "Line Color", "Color of the solution line", new AColor(0xFF00FF00, true), TCAColor.INSTANCE));
+        addParameter("lineWidth", new FeatureParameter<Float>("lineWidth", "Line Thickness", "Thickness of the solution line",1.0f, TCFloat.INSTANCE));
 
-        addParameter("targetColor", new FeatureParameter<AColor>("targetColor", "Target Color", "Color of the target button", new AColor(0x5500FFFF, true), "acolor"));
-        addParameter("textColor1", new FeatureParameter<AColor>("textColor1", "Text Color", "Color of the text (next step)", new AColor(0xFF00FF00, true), "acolor"));
-        addParameter("textColor2", new FeatureParameter<AColor>("textColor2", "Text Color", "Color of the text (others)", new AColor(0xFF000000, true), "acolor"));
+        addParameter("targetColor", new FeatureParameter<AColor>("targetColor", "Target Color", "Color of the target button", new AColor(0x5500FFFF, true), TCAColor.INSTANCE));
+        addParameter("textColor1", new FeatureParameter<AColor>("textColor1", "Text Color", "Color of the text (next step)", new AColor(0xFF00FF00, true), TCAColor.INSTANCE));
+        addParameter("textColor2", new FeatureParameter<AColor>("textColor2", "Text Color", "Color of the text (others)", new AColor(0xFF000000, true), TCAColor.INSTANCE));
     }
     public AColor getLineColor() {
         return this.<AColor>getParameter("lineColor").getValue();
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/solvers/FeatureSolverIcefill.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/solvers/FeatureSolverIcefill.java
index b21a9098..f9415f75 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/solvers/FeatureSolverIcefill.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/solvers/FeatureSolverIcefill.java
@@ -19,6 +19,8 @@
 package kr.syeyoung.dungeonsguide.mod.features.impl.solvers;
 
 import kr.syeyoung.dungeonsguide.mod.config.types.AColor;
+import kr.syeyoung.dungeonsguide.mod.config.types.TCAColor;
+import kr.syeyoung.dungeonsguide.mod.config.types.TCFloat;
 import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
 import kr.syeyoung.dungeonsguide.mod.features.SimpleFeature;
 
@@ -28,8 +30,8 @@ public class FeatureSolverIcefill extends SimpleFeature {
     public FeatureSolverIcefill() {
         super("Dungeon.Solvers.Floor 3+", "Icepath (Advanced)", "Calculates solution for icepath puzzle and displays it to user",  "solver.icepath");
         this.parameters = new LinkedHashMap<>();
-        addParameter("lineColor", new FeatureParameter<AColor>("lineColor", "Line Color", "Color of the solution line", new AColor(0xFF00FF00, true), "acolor"));
-        addParameter("lineWidth", new FeatureParameter<Float>("lineWidth", "Line Thickness", "Thickness of the solution line",1.0f, "float"));
+        addParameter("lineColor", new FeatureParameter<AColor>("lineColor", "Line Color", "Color of the solution line", new AColor(0xFF00FF00, true), TCAColor.INSTANCE));
+        addParameter("lineWidth", new FeatureParameter<Float>("lineWidth", "Line Thickness", "Thickness of the solution line",1.0f, TCFloat.INSTANCE));
     }
     public AColor getLineColor() {
         return this.<AColor>getParameter("lineColor").getValue();
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/solvers/FeatureSolverKahoot.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/solvers/FeatureSolverKahoot.java
index fdd1ed7c..1831e7c6 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/solvers/FeatureSolverKahoot.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/solvers/FeatureSolverKahoot.java
@@ -19,6 +19,7 @@
 package kr.syeyoung.dungeonsguide.mod.features.impl.solvers;
 
 import kr.syeyoung.dungeonsguide.mod.config.types.AColor;
+import kr.syeyoung.dungeonsguide.mod.config.types.TCAColor;
 import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
 import kr.syeyoung.dungeonsguide.mod.features.SimpleFeature;
 
@@ -26,7 +27,7 @@ public class FeatureSolverKahoot extends SimpleFeature {
     public FeatureSolverKahoot() {
         super("Dungeon.Solvers.Floor 4+", "Quiz", "Highlights the correct solution for trivia puzzle",  "solver.trivia");
 
-        addParameter("targetColor", new FeatureParameter<AColor>("targetColor", "Target Color", "Color of the solution box", new AColor(0,255,0,50), "acolor"));
+        addParameter("targetColor", new FeatureParameter<AColor>("targetColor", "Target Color", "Color of the solution box", new AColor(0,255,0,50), TCAColor.INSTANCE));
     }
 
     public AColor getTargetColor() {
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/solvers/FeatureSolverRiddle.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/solvers/FeatureSolverRiddle.java
index da84f379..ccd2d26a 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/solvers/FeatureSolverRiddle.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/solvers/FeatureSolverRiddle.java
@@ -19,6 +19,7 @@
 package kr.syeyoung.dungeonsguide.mod.features.impl.solvers;
 
 import kr.syeyoung.dungeonsguide.mod.config.types.AColor;
+import kr.syeyoung.dungeonsguide.mod.config.types.TCAColor;
 import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
 import kr.syeyoung.dungeonsguide.mod.features.SimpleFeature;
 
@@ -26,7 +27,7 @@ public class FeatureSolverRiddle extends SimpleFeature {
     public FeatureSolverRiddle() {
         super("Dungeon.Solvers.Any Floor", "Riddle", "Highlights the correct box after clicking on all 3 weirdos",  "solver.riddle");
 
-        addParameter("targetColor", new FeatureParameter<AColor>("targetColor", "Target Color", "Color of the solution box", new AColor(0,255,0,50), "acolor"));
+        addParameter("targetColor", new FeatureParameter<AColor>("targetColor", "Target Color", "Color of the solution box", new AColor(0,255,0,50), TCAColor.INSTANCE));
     }
 
     public AColor getTargetColor() {
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/solvers/FeatureSolverSilverfish.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/solvers/FeatureSolverSilverfish.java
index a014b09e..053f452b 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/solvers/FeatureSolverSilverfish.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/solvers/FeatureSolverSilverfish.java
@@ -19,6 +19,8 @@
 package kr.syeyoung.dungeonsguide.mod.features.impl.solvers;
 
 import kr.syeyoung.dungeonsguide.mod.config.types.AColor;
+import kr.syeyoung.dungeonsguide.mod.config.types.TCAColor;
+import kr.syeyoung.dungeonsguide.mod.config.types.TCFloat;
 import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
 import kr.syeyoung.dungeonsguide.mod.features.SimpleFeature;
 
@@ -28,8 +30,8 @@ public class FeatureSolverSilverfish extends SimpleFeature {
     public FeatureSolverSilverfish() {
         super("Dungeon.Solvers.Floor 3+", "Silverfish (Advanced)", "Actively calculates solution for silverfish puzzle and displays it to user",  "solver.silverfish");
         this.parameters = new LinkedHashMap<>();
-        addParameter("lineColor", new FeatureParameter<AColor>("lineColor", "Line Color", "Color of the solution line", new AColor(0xFF00FF00, true), "acolor", nval -> lineColor = nval));
-        addParameter("lineWidth", new FeatureParameter<Float>("lineWidth", "Line Thickness", "Thickness of the solution line",1.0f, "float", nval -> lineWidth = nval));
+        addParameter("lineColor", new FeatureParameter<AColor>("lineColor", "Line Color", "Color of the solution line", new AColor(0xFF00FF00, true), TCAColor.INSTANCE, nval -> lineColor = nval));
+        addParameter("lineWidth", new FeatureParameter<Float>("lineWidth", "Line Thickness", "Thickness of the solution line",1.0f, TCFloat.INSTANCE, nval -> lineWidth = nval));
     }
 
     AColor lineColor;
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/solvers/FeatureSolverTeleport.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/solvers/FeatureSolverTeleport.java
index f2a6adf2..da9084e6 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/solvers/FeatureSolverTeleport.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/solvers/FeatureSolverTeleport.java
@@ -19,6 +19,7 @@
 package kr.syeyoung.dungeonsguide.mod.features.impl.solvers;
 
 import kr.syeyoung.dungeonsguide.mod.config.types.AColor;
+import kr.syeyoung.dungeonsguide.mod.config.types.TCAColor;
 import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
 import kr.syeyoung.dungeonsguide.mod.features.SimpleFeature;
 
@@ -26,8 +27,8 @@ public class FeatureSolverTeleport extends SimpleFeature {
     public FeatureSolverTeleport() {
         super("Dungeon.Solvers.Any Floor", "Teleport", "Shows teleport pads you've visited in a teleport maze room",  "solver.teleport");
 
-        addParameter("targetColor", new FeatureParameter<AColor>("targetColor", "Solution Color", "Color of the solution teleport pad", new AColor(0,255,0,100), "acolor"));
-        addParameter("targetColor2", new FeatureParameter<AColor>("targetColor2", "Not-Solution Color", "Color of the solution teleport pads you've been to", new AColor(255,0,0,100), "acolor"));
+        addParameter("targetColor", new FeatureParameter<AColor>("targetColor", "Solution Color", "Color of the solution teleport pad", new AColor(0,255,0,100), TCAColor.INSTANCE));
+        addParameter("targetColor2", new FeatureParameter<AColor>("targetColor2", "Not-Solution Color", "Color of the solution teleport pads you've been to", new AColor(255,0,0,100), TCAColor.INSTANCE));
     }
 
     public AColor getTargetColor() {
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/solvers/FeatureSolverTictactoe.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/solvers/FeatureSolverTictactoe.java
index cafe97b3..8f509242 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/solvers/FeatureSolverTictactoe.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/solvers/FeatureSolverTictactoe.java
@@ -19,6 +19,7 @@
 package kr.syeyoung.dungeonsguide.mod.features.impl.solvers;
 
 import kr.syeyoung.dungeonsguide.mod.config.types.AColor;
+import kr.syeyoung.dungeonsguide.mod.config.types.TCAColor;
 import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
 import kr.syeyoung.dungeonsguide.mod.features.SimpleFeature;
 
@@ -26,8 +27,8 @@ public class FeatureSolverTictactoe extends SimpleFeature {
     public FeatureSolverTictactoe() {
         super("Dungeon.Solvers.Any Floor", "Tictactoe", "Shows the best move that could be taken by player in the tictactoe room", "solver.tictactoe");
 
-        addParameter("targetColor", new FeatureParameter<AColor>("targetColor", "Target Color", "Color of the solution box during your turn", new AColor(0,255,255,50), "acolor"));
-        addParameter("targetColor2", new FeatureParameter<AColor>("targetColor", "Target Color", "Color of the solution box during enemy turn", new AColor(255,201,0,50), "acolor"));
+        addParameter("targetColor", new FeatureParameter<AColor>("targetColor", "Target Color", "Color of the solution box during your turn", new AColor(0,255,255,50), TCAColor.INSTANCE));
+        addParameter("targetColor2", new FeatureParameter<AColor>("targetColor", "Target Color", "Color of the solution box during enemy turn", new AColor(255,201,0,50), TCAColor.INSTANCE));
     }
 
     public AColor getTargetColor() {
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/text/TextHUDFeature.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/text/TextHUDFeature.java
index 3c0d21ca..4235d79f 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/text/TextHUDFeature.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/text/TextHUDFeature.java
@@ -18,24 +18,15 @@
 
 package kr.syeyoung.dungeonsguide.mod.features.text;
 
-import com.google.common.base.Supplier;
-import com.google.gson.JsonObject;
-import kr.syeyoung.dungeonsguide.mod.config.guiconfig.ConfigPanelCreator;
-import kr.syeyoung.dungeonsguide.mod.config.guiconfig.MFeatureEdit;
-import kr.syeyoung.dungeonsguide.mod.config.guiconfig.MParameterEdit;
-import kr.syeyoung.dungeonsguide.mod.config.guiconfig.RootConfigPanel;
 import kr.syeyoung.dungeonsguide.mod.config.guiconfig.location2.MarkerProvider;
-import kr.syeyoung.dungeonsguide.mod.config.types.AColor;
+import kr.syeyoung.dungeonsguide.mod.config.types.*;
 import kr.syeyoung.dungeonsguide.mod.events.annotations.DGEventHandler;
 import kr.syeyoung.dungeonsguide.mod.events.impl.DGTickEvent;
 import kr.syeyoung.dungeonsguide.mod.features.AbstractHUDFeature;
 import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter;
-import kr.syeyoung.dungeonsguide.mod.gui.MPanel;
-import kr.syeyoung.dungeonsguide.mod.gui.elements.MFloatSelectionButton;
-import kr.syeyoung.dungeonsguide.mod.gui.elements.MPassiveLabelAndElement;
-import kr.syeyoung.dungeonsguide.mod.gui.elements.MStringSelectionButton;
 import kr.syeyoung.dungeonsguide.mod.guiv2.DomElement;
 import kr.syeyoung.dungeonsguide.mod.guiv2.Widget;
+import kr.syeyoung.dungeonsguide.mod.guiv2.elements.CompatLayer;
 import kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.BreakWord;
 import kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.RichText;
 import kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.TextSpan;
@@ -55,15 +46,10 @@ import java.util.*;
 public abstract class TextHUDFeature extends AbstractHUDFeature implements StyledTextProvider {
     protected TextHUDFeature(String category, String name, String description, String key) {
         super(category, name, description, key);
-        addParameter("textStylesNEW", new FeatureParameter<List<TextStyle>>("textStylesNEW", "", "", new ArrayList<TextStyle>(), "list_textStyle"));
-        addParameter("alignment", new FeatureParameter<String>("alignment", "Alignment", "Alignment", "LEFT", "string", (change) -> {
-            richText.setAlign(
-                    change.equals("LEFT") ? RichText.TextAlign.LEFT :
-                            change.equals("CENTER") ? RichText.TextAlign.CENTER :
-                                    change.equals("RIGHT") ? RichText.TextAlign.RIGHT : RichText.TextAlign.LEFT
-            );
-        }));
-        addParameter("scale", new FeatureParameter<Float>("scale", "Scale", "Scale", 1.0f, "float"));
+        addParameter("textStylesNEW", new FeatureParameter<List<TextStyle>>("textStylesNEW", "", "", new ArrayList<TextStyle>(), TCTextStyleList.INSTANCE)
+                .setWidgetGenerator((param) -> new CompatLayer(new PanelTextParameterConfig(TextHUDFeature.this))));
+        addParameter("alignment", new FeatureParameter<RichText.TextAlign>("alignment", "Alignment", "Alignment", RichText.TextAlign.LEFT, new TCEnum<>(RichText.TextAlign.values()), richText::setAlign));
+        addParameter("scale", new FeatureParameter<Float>("scale", "Scale", "Scale", 1.0f, TCFloat.INSTANCE));
     }
 
     @Override
@@ -118,7 +104,7 @@ public abstract class TextHUDFeature extends AbstractHUDFeature implements Style
         GlStateManager.scale(scale, scale, 0);
 
         StyledTextRenderer.drawTextWithStylesAssociated(asd, 0, 0, 100, getStylesMap(),
-                StyledTextRenderer.Alignment.valueOf(TextHUDFeature.this.<String>getParameter("alignment").getValue()));
+                StyledTextRenderer.Alignment.valueOf(TextHUDFeature.this.<RichText.TextAlign>getParameter("alignment").getValue().name()));
     }
 
     @RequiredArgsConstructor
@@ -126,19 +112,19 @@ public abstract class TextHUDFeature extends AbstractHUDFeature implements Style
         public final TextHUDFeature hudFeature;
         @Override
         public List<Position> getMarkers() {
-            String change = hudFeature.<String>getParameter("alignment").getValue();
+            RichText.TextAlign change = hudFeature.<RichText.TextAlign>getParameter("alignment").getValue();
             Rect relBound = getDomElement().getRelativeBound();
-            if (change.equals("LEFT")) {
+            if (change == RichText.TextAlign.LEFT) {
                 return Arrays.asList(
                         new Position(0, 0),
                         new Position(0, relBound.getHeight())
                 );
-            } else if (change.equals("CENTER")) {
+            } else if (change == RichText.TextAlign.CENTER) {
                 return Arrays.asList(
                         new Position(relBound.getWidth() /2, 0),
                         new Position(relBound.getWidth() /2, relBound.getHeight())
                 );
-            } else if (change.equals("RIGHT")) {
+            } else if (change == RichText.TextAlign.RIGHT) {
                 return Arrays.asList(
                         new Position(relBound.getWidth(), 0),
                         new Position(relBound.getWidth(), relBound.getHeight())
@@ -155,11 +141,8 @@ public abstract class TextHUDFeature extends AbstractHUDFeature implements Style
                     ParentDelegatingTextStyle.ofDefault(),
                     ""
             ), BreakWord.WORD, false, RichText.TextAlign.LEFT);
-            String change = hudFeature.<String>getParameter("alignment").getValue();
             richText.setAlign(
-                    change.equals("LEFT") ? RichText.TextAlign.LEFT :
-                            change.equals("CENTER") ? RichText.TextAlign.CENTER :
-                                    change.equals("RIGHT") ? RichText.TextAlign.RIGHT : RichText.TextAlign.LEFT
+                    hudFeature.<RichText.TextAlign>getParameter("alignment").getValue()
             );
 
             ParentDelegatingTextStyle defaultStyle = ParentDelegatingTextStyle.ofDefault();
@@ -227,33 +210,6 @@ public abstract class TextHUDFeature extends AbstractHUDFeature implements Style
     }
 
 
-    @Override
-    public String getEditRoute(RootConfigPanel rootConfigPanel) {
-        ConfigPanelCreator.map.put("base." + getKey() , new Supplier<MPanel>() {
-            @Override
-            public MPanel get() {
-
-                MFeatureEdit featureEdit = new MFeatureEdit(TextHUDFeature.this, rootConfigPanel);
-                featureEdit.addParameterEdit("textStyleNEW", new PanelTextParameterConfig(TextHUDFeature.this));
-
-                StyledTextRenderer.Alignment alignment = StyledTextRenderer.Alignment.valueOf(TextHUDFeature.this.<String>getParameter("alignment").getValue());
-                MStringSelectionButton mStringSelectionButton = new MStringSelectionButton(Arrays.asList("LEFT", "CENTER", "RIGHT"), alignment.name());
-                mStringSelectionButton.setOnUpdate(() -> {
-                    TextHUDFeature.this.<String>getParameter("alignment").setValue(mStringSelectionButton.getSelected());
-                });
-                featureEdit.addParameterEdit("alignment", new MParameterEdit(TextHUDFeature.this, TextHUDFeature.this.<String>getParameter("alignment"), rootConfigPanel, mStringSelectionButton, (a) -> false));
-
-                for (FeatureParameter parameter: getParameters()) {
-                    if (parameter.getKey().equals("textStylesNEW")) continue;
-                    if (parameter.getKey().equals("alignment")) continue;
-                    featureEdit.addParameterEdit(parameter.getKey(), new MParameterEdit(TextHUDFeature.this, parameter, rootConfigPanel));
-                }
-                return featureEdit;
-            }
-        });
-        return "base." + getKey() ;
-    }
-
     @Override
     public void getTooltipForEditor(List<Widget> widgets) {
         super.getTooltipForEditor(widgets);
@@ -278,13 +234,4 @@ public abstract class TextHUDFeature extends AbstractHUDFeature implements Style
         stylesMap = null;
     }
 
-    @Override
-    public void loadConfig(JsonObject jsonObject) {
-        super.loadConfig(jsonObject);
-        StyledTextRenderer.Alignment alignment;
-        try {
-            alignment = StyledTextRenderer.Alignment.valueOf(TextHUDFeature.this.<String>getParameter("alignment").getValue());
-        } catch (Exception e) {alignment = StyledTextRenderer.Alignment.LEFT;}
-        TextHUDFeature.this.<String>getParameter("alignment").setValue(alignment.name());
-    }
 }
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/MPanel.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/MPanel.java
index 3b36a509..5e4ef937 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/MPanel.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/gui/MPanel.java
@@ -104,7 +104,7 @@ public class MPanel {
 
     public void remove(MPanel panel) {
         if (panel != null)
-        panel.setParent(null);
+            panel.setParent(null);
         this.childComponents.remove(panel);
     }
 
@@ -115,7 +115,6 @@ public class MPanel {
     private boolean ignoreBoundOnClip;
 
     public void render0(double scale, Point parentPoint, Rectangle parentClip, int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks) { // 0,0 - a a
-
         lastParentPoint = parentPoint;
         int relMousex = relMousex0 - getBounds().x;
         int relMousey = relMousey0 - getBounds().y;
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/AbsXY.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/AbsXY.java
index 0f5a97d1..49041c0f 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/AbsXY.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/AbsXY.java
@@ -56,7 +56,7 @@ public class AbsXY extends AnnotatedExportOnlyWidget implements Layouter {
     @Override
     public Size layout(DomElement buildContext, ConstraintBox constraintBox) {
         DomElement child = buildContext.getChildren().get(0);
-        Size size = child.getLayouter().layout(buildContext, new ConstraintBox(
+        Size size = child.getLayouter().layout(child, new ConstraintBox(
                 0,constraintBox.getMaxWidth() - x.getValue(), 0, constraintBox.getMaxHeight()-y.getValue()
         ));
         child.setRelativeBound(new Rect(x.getValue(), y.getValue(), size.getWidth(), size.getHeight()));
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/Border.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/Border.java
index d9160752..b70a6e69 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/Border.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/Border.java
@@ -93,7 +93,7 @@ public class Border extends AnnotatedExportOnlyWidget implements Layouter {
             if (top != null)
                 th= top.getLayouter().layout(top, new ConstraintBox(dimension.getWidth() + lw + rw, dimension.getWidth() + lw + rw,  th, th)).getHeight();
             if (bottom != null)
-                bh = bottom.getLayouter().layout(buildContext, new ConstraintBox(dimension.getWidth() + lw + rw, dimension.getWidth() + lw + rw,  bh,bh)).getHeight();
+                bh = bottom.getLayouter().layout(bottom, new ConstraintBox(dimension.getWidth() + lw + rw, dimension.getWidth() + lw + rw,  bh,bh)).getHeight();
         }
 
         if (top != null)
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/CompatLayer.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/CompatLayer.java
new file mode 100644
index 00000000..ba6d3ea5
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/CompatLayer.java
@@ -0,0 +1,169 @@
+/*
+ * 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.mod.guiv2.elements;
+
+import kr.syeyoung.dungeonsguide.mod.gui.MPanel;
+import kr.syeyoung.dungeonsguide.mod.gui.elements.MTooltip;
+import kr.syeyoung.dungeonsguide.mod.guiv2.DomElement;
+import kr.syeyoung.dungeonsguide.mod.guiv2.Widget;
+import kr.syeyoung.dungeonsguide.mod.guiv2.elements.popups.AbsLocationPopup;
+import kr.syeyoung.dungeonsguide.mod.guiv2.elements.popups.PopupMgr;
+import kr.syeyoung.dungeonsguide.mod.guiv2.layouter.Layouter;
+import kr.syeyoung.dungeonsguide.mod.guiv2.primitive.ConstraintBox;
+import kr.syeyoung.dungeonsguide.mod.guiv2.primitive.Size;
+import kr.syeyoung.dungeonsguide.mod.guiv2.renderer.Renderer;
+import kr.syeyoung.dungeonsguide.mod.guiv2.renderer.RenderingContext;
+import kr.syeyoung.dungeonsguide.mod.utils.cursor.EnumCursor;
+import net.minecraft.client.Minecraft;
+import org.lwjgl.opengl.GL11;
+
+import java.awt.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class CompatLayer extends Widget implements Layouter, Renderer {
+    private MPanel panel;
+    private Rectangle force;
+
+    public CompatLayer(MPanel panel) {
+        this(panel, null);
+    }
+
+    List<AbsLocationPopup> tooltips = new ArrayList<>();
+    public CompatLayer(MPanel panel, Rectangle force) {
+        this.panel = panel;
+        this.force = force;
+        panel.setParent(new MPanel() {
+            @Override
+            public void setCursor(EnumCursor enumCursor) {
+                getDomElement().setCursor(enumCursor);
+            }
+
+            @Override
+            public int getTooltipsOpen() {
+                return 0;
+            }
+
+            @Override
+            public void openTooltip(MTooltip mPanel) {
+                Rectangle bounds = mPanel.getBounds();
+                AbsLocationPopup absLocationPopup = new AbsLocationPopup(bounds.getX(), bounds.getY(), new CompatLayer(mPanel, bounds), true);
+                PopupMgr.getPopupMgr(getDomElement()).openPopup(absLocationPopup, (a) -> {tooltips.remove(absLocationPopup);});
+                tooltips.add(absLocationPopup);
+            }
+        });
+    }
+
+    @Override
+    public void onUnmount() {
+        super.onUnmount();
+        tooltips.forEach(PopupMgr.getPopupMgr(getDomElement())::closePopup);
+    }
+
+    @Override
+    public List<Widget> build(DomElement buildContext) {
+        return Collections.emptyList();
+    }
+
+
+
+    @Override
+    public boolean mouseClicked(int absMouseX, int absMouseY, double relMouseX, double relMouseY, int mouseButton) {
+        getDomElement().obtainFocus();
+        double scale = getDomElement().getAbsBounds().getWidth() / getDomElement().getSize().getWidth();
+        return panel.mouseClicked0( (int)(absMouseX / scale), (int)(absMouseY / scale), (int)relMouseX,(int) relMouseY, mouseButton);
+    }
+
+    @Override
+    public void mouseClickMove(int absMouseX, int absMouseY, double relMouseX, double relMouseY, int clickedMouseButton, long timeSinceLastClick) {
+        double scale = getDomElement().getAbsBounds().getWidth() / getDomElement().getSize().getWidth();
+        panel.mouseClickMove0( (int)(absMouseX / scale), (int)(absMouseY / scale),  (int)relMouseX, (int)relMouseY, clickedMouseButton, timeSinceLastClick);
+    }
+
+    @Override
+    public void mouseReleased(int absMouseX, int absMouseY, double relMouseX, double relMouseY, int state) {
+        double scale = getDomElement().getAbsBounds().getWidth() / getDomElement().getSize().getWidth();
+        panel.mouseReleased0( (int)(absMouseX / scale), (int)(absMouseY / scale), (int)relMouseX,(int) relMouseY, state);
+    }
+
+    @Override
+    public boolean mouseMoved(int absMouseX, int absMouseY, double relMouseX0, double relMouseY0) {
+        double scale = getDomElement().getAbsBounds().getWidth() / getDomElement().getSize().getWidth();
+        panel.mouseMoved0( (int)(absMouseX / scale), (int)(absMouseY / scale), (int)relMouseX0, (int)relMouseY0);
+        return true;
+    }
+
+    @Override
+    public boolean mouseScrolled(int absMouseX, int absMouseY, double relMouseX0, double relMouseY0, int scrollAmount) {
+        double scale = getDomElement().getAbsBounds().getWidth() / getDomElement().getSize().getWidth();
+        panel.mouseScrolled0( (int)(absMouseX / scale), (int)(absMouseY / scale), (int)relMouseX0, (int)relMouseY0, scrollAmount);
+        return true;
+    }
+
+    @Override
+    public void keyPressed(char typedChar, int keyCode) {
+        panel.keyPressed0(typedChar, keyCode);
+    }
+
+    @Override
+    public void keyReleased(char typedChar, int keyCode) {
+        panel.keyReleased0(typedChar, keyCode);
+    }
+
+    @Override
+    public void keyHeld(char typedChar, int keyCode) {
+        panel.keyHeld0(typedChar, keyCode);
+    }
+
+    @Override
+    public Size layout(DomElement buildContext, ConstraintBox constraintBox) {
+        Dimension dimension = force == null ? panel.getPreferredSize() : force.getSize();
+        panel.resize((int) constraintBox.getMaxWidth(), (int) constraintBox.getMaxHeight());
+        if (panel.getBounds().getWidth() != 0) dimension = panel.getSize();
+
+        panel.setBounds(new Rectangle(0,0, (int) dimension.getWidth(), (int) dimension.getHeight()));
+        return new Size(dimension.getWidth(), dimension.getHeight());
+    }
+
+    @Override
+    public void doRender(int absMouseX, int absMouseY, double relMouseX, double relMouseY, float partialTicks, RenderingContext context, DomElement buildContext) {
+        double scale = getDomElement().getAbsBounds().getWidth() / getDomElement().getSize().getWidth();
+
+        Rectangle originalRect = context.currentClip();
+        Rectangle rectangle = originalRect == null ? null : originalRect.getBounds();
+        boolean isNotNull = rectangle != null;
+        if (rectangle == null) rectangle = new Rectangle(0,0,Minecraft.getMinecraft().displayWidth, Minecraft.getMinecraft().displayHeight);
+
+        rectangle.y = Minecraft.getMinecraft().displayHeight - rectangle.y - rectangle.height;
+        rectangle.width /= scale;
+        rectangle.height /= scale;
+        rectangle.x /= scale;
+        rectangle.y /= scale;
+
+//        System.out.println(rectangle);
+        panel.render0(scale, new Point((int) (getDomElement().getAbsBounds().getX() / scale), (int) (getDomElement().getAbsBounds().getY() /scale)),
+                rectangle, (int)(absMouseX / scale), (int)(absMouseY / scale), (int)relMouseX, (int)relMouseY, partialTicks);
+
+        if (isNotNull) {
+            GL11.glEnable(GL11.GL_SCISSOR_TEST);
+            GL11.glScissor(originalRect.x, originalRect.y, originalRect.width, originalRect.height);
+        }
+    }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/NegativeStencil.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/NegativeStencil.java
new file mode 100644
index 00000000..0a2553ca
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/NegativeStencil.java
@@ -0,0 +1,112 @@
+/*
+ * 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.mod.guiv2.elements;
+
+import kr.syeyoung.dungeonsguide.mod.guiv2.BindableAttribute;
+import kr.syeyoung.dungeonsguide.mod.guiv2.DomElement;
+import kr.syeyoung.dungeonsguide.mod.guiv2.Widget;
+import kr.syeyoung.dungeonsguide.mod.guiv2.layouter.Layouter;
+import kr.syeyoung.dungeonsguide.mod.guiv2.primitive.Rect;
+import kr.syeyoung.dungeonsguide.mod.guiv2.renderer.Renderer;
+import kr.syeyoung.dungeonsguide.mod.guiv2.renderer.RenderingContext;
+import kr.syeyoung.dungeonsguide.mod.guiv2.xml.AnnotatedExportOnlyWidget;
+import kr.syeyoung.dungeonsguide.mod.guiv2.xml.annotations.Export;
+import net.minecraft.client.renderer.GlStateManager;
+import org.lwjgl.opengl.GL11;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class NegativeStencil extends AnnotatedExportOnlyWidget implements Renderer {
+    @Export(attributeName = "_")
+    public final BindableAttribute<Widget> children = new BindableAttribute<>(Widget.class);
+    @Export(attributeName = "_stencil")
+    public final BindableAttribute<Widget> stencil = new BindableAttribute<>(Widget.class);
+
+    @Override
+    public List<Widget> build(DomElement buildContext) {
+        return Arrays.asList(children.getValue(), stencil.getValue());
+    }
+
+    @Override
+    protected Layouter createLayouter() {
+        return Stack.StackingLayouter.INSTANCE;
+    }
+
+    @Override
+    public void doRender(int absMouseX, int absMouseY, double relMouseX, double relMouseY, float partialTicks, RenderingContext context, DomElement buildContext) {
+        DomElement theThingToDraw = buildContext.getChildren().get(0);
+        DomElement stencil = buildContext.getChildren().get(1);
+
+        GL11.glEnable(GL11.GL_STENCIL_TEST);
+        GL11.glClearStencil(0);
+        GL11.glClear(GL11.GL_STENCIL_BUFFER_BIT);
+
+        GL11.glStencilMask(0xFF);
+        GL11.glColorMask(false, false, false, false);
+        GL11.glStencilFunc(GL11.GL_ALWAYS, 1, 0xFF);
+        GL11.glStencilOp(GL11.GL_KEEP, GL11.GL_REPLACE, GL11.GL_REPLACE);
+
+        GlStateManager.pushMatrix();
+        Rect original = stencil.getRelativeBound();
+        GlStateManager.translate(original.getX(), original.getY(), 0);
+
+        double absXScale = buildContext.getAbsBounds().getWidth() / buildContext.getSize().getWidth();
+        double absYScale = buildContext.getAbsBounds().getHeight() / buildContext.getSize().getHeight();
+
+        Rect elementABSBound = new Rect(
+                (buildContext.getAbsBounds().getX() + original.getX() * absXScale),
+                (buildContext.getAbsBounds().getY() + original.getY() * absYScale),
+                (original.getWidth() * absXScale),
+                (original.getHeight() * absYScale)
+        );
+        stencil.setAbsBounds(elementABSBound);
+
+        stencil.getRenderer().doRender(absMouseX, absMouseY,
+                relMouseX - original.getX(),
+                relMouseY - original.getY(), partialTicks,context, stencil);
+        GlStateManager.popMatrix();
+
+
+        GL11.glStencilFunc(GL11.GL_EQUAL, 0, 0xFF);
+        GL11.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_KEEP);
+        GL11.glColorMask(true, true, true, true);
+
+
+        original = theThingToDraw.getRelativeBound();
+        GlStateManager.translate(original.getX(), original.getY(), 0);
+
+        absXScale = buildContext.getAbsBounds().getWidth() / buildContext.getSize().getWidth();
+        absYScale = buildContext.getAbsBounds().getHeight() / buildContext.getSize().getHeight();
+
+        elementABSBound = new Rect(
+                (buildContext.getAbsBounds().getX() + original.getX() * absXScale),
+                (buildContext.getAbsBounds().getY() + original.getY() * absYScale),
+                (original.getWidth() * absXScale),
+                (original.getHeight() * absYScale)
+        );
+        theThingToDraw.setAbsBounds(elementABSBound);
+
+        theThingToDraw.getRenderer().doRender(absMouseX, absMouseY,
+                relMouseX - original.getX(),
+                relMouseY - original.getY(), partialTicks,context, theThingToDraw);
+
+        GL11.glDisable(GL11.GL_STENCIL_TEST);
+    }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/TextField.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/TextField.java
index 1f59f8f4..fde24655 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/TextField.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/TextField.java
@@ -116,6 +116,7 @@ public class TextField extends AnnotatedExportOnlyWidget implements Renderer, La
         // draw selection
         if (getDomElement().isFocused()) {
             if (selectionStart != -1) {
+                if (selectionEnd > text.length()) selectionEnd = text.length();
                 int startX = (int) (fr.getStringWidth(text.substring(0, selectionStart)) - xOffset);
                 int endX = (int) (fr.getStringWidth(text.substring(0, selectionEnd)) - xOffset);
                 Gui.drawRect( (3 + startX), y,  (3 + endX), y + fr.FONT_HEIGHT, 0xFF00FF00);
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/popups/AbsLocationPopup.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/popups/AbsLocationPopup.java
index e9331b33..29bc4614 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/popups/AbsLocationPopup.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/elements/popups/AbsLocationPopup.java
@@ -21,6 +21,7 @@ package kr.syeyoung.dungeonsguide.mod.guiv2.elements.popups;
 import kr.syeyoung.dungeonsguide.mod.guiv2.BindableAttribute;
 import kr.syeyoung.dungeonsguide.mod.guiv2.DomElement;
 import kr.syeyoung.dungeonsguide.mod.guiv2.Widget;
+import kr.syeyoung.dungeonsguide.mod.guiv2.layouter.Layouter;
 import kr.syeyoung.dungeonsguide.mod.guiv2.primitive.Rect;
 import kr.syeyoung.dungeonsguide.mod.guiv2.primitive.Size;
 import kr.syeyoung.dungeonsguide.mod.guiv2.xml.AnnotatedImportOnlyWidget;
@@ -38,6 +39,8 @@ public class AbsLocationPopup extends AnnotatedImportOnlyWidget {
     public final BindableAttribute<DomElement> ref = new BindableAttribute<>(DomElement.class);
     @Bind(variableName = "child")
     public final BindableAttribute<Widget> child = new BindableAttribute<>(Widget.class);
+    @Bind(variableName = "size")
+    public final BindableAttribute<Size> size = new BindableAttribute<>(Size.class, new Size(0,0));
 
     public final BindableAttribute<Double> absX = new BindableAttribute<>(Double.class);
     public final BindableAttribute<Double> absY = new BindableAttribute<>(Double.class);
@@ -48,6 +51,7 @@ public class AbsLocationPopup extends AnnotatedImportOnlyWidget {
         absY.setValue(y);
         absX.addOnUpdate(this::updatePos);
         absY.addOnUpdate(this::updatePos);
+        size.addOnUpdate((old, neu) -> updatePos(0,0));
         this.child.setValue(child);
         this.autoclose = autoclose;
     }
@@ -57,6 +61,7 @@ public class AbsLocationPopup extends AnnotatedImportOnlyWidget {
         y.exportTo(this.absY);
         absX.addOnUpdate(this::updatePos);
         absY.addOnUpdate(this::updatePos);
+        size.addOnUpdate((old, neu) -> updatePos(0,0));
         this.child.setValue(child);
         this.autoclose = autoclose;
     }
@@ -70,11 +75,13 @@ public class AbsLocationPopup extends AnnotatedImportOnlyWidget {
         PopupMgr popupMgr = PopupMgr.getPopupMgr(getDomElement());
         Rect rect = popupMgr.getDomElement().getAbsBounds();
         Size rel = popupMgr.getDomElement().getSize();
+
+        Size size = this.size.getValue();
         this.x.setValue(
-                (absX.getValue() - rect.getX()) * rel.getWidth() / rect.getWidth()
+                Layouter.clamp((absX.getValue() - rect.getX()) * rel.getWidth() / rect.getWidth(), 0, rel.getWidth()-size.getWidth())
         );
         this.y.setValue(
-                (absY.getValue() - rect.getY()) * rel.getHeight() / rect.getHeight()
+                Layouter.clamp((absY.getValue() - rect.getY()) * rel.getHeight() / rect.getHeight(), 0, rel.getHeight() - size.getHeight())
         );
     }
 
@@ -85,4 +92,9 @@ public class AbsLocationPopup extends AnnotatedImportOnlyWidget {
         }
         return false;
     }
+
+    @Override
+    public boolean mouseMoved(int absMouseX, int absMouseY, double relMouseX0, double relMouseY0) {
+        return true;
+    }
 }
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/renderer/RenderingContext.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/renderer/RenderingContext.java
index ab668f1b..87097e00 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/renderer/RenderingContext.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/renderer/RenderingContext.java
@@ -86,6 +86,10 @@ public class RenderingContext {
 
     public Stack<Rectangle> clips = new Stack<>();
 
+    public Rectangle currentClip() {
+        return clips.empty() ? null : clips.peek();
+    }
+
     public void pushClip(Rect absBounds, Size size, double x, double y, double width, double height) {
         if (width < 0 || height < 0) {
             width = 0;
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/xml/DomElementRegistry.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/xml/DomElementRegistry.java
index f0d77ec9..a1575d33 100644
--- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/xml/DomElementRegistry.java
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/guiv2/xml/DomElementRegistry.java
@@ -81,6 +81,7 @@ public class DomElementRegistry {
         register("CircularRect", new ExportedWidgetConverter(CircularRect::new));
         register("Navigator", new ExportedWidgetConverter(Navigator::new));
         register("Stencil", new ExportedWidgetConverter(Stencil::new));
+        register("InvertStencil", new ExportedWidgetConverter(NegativeStencil::new));
         register("WrapGrid", new ExportedWidgetConverter(Wrap::new));
 
         register("ColorButton", new DelegatingWidgetConverter(new ResourceLocation("dungeonsguide:gui/elements/simpleButton.gui")));
diff --git a/mod/src/main/resources/assets/dungeonsguide/gui/config/normalconfig.gui b/mod/src/main/resources/assets/dungeonsguide/gui/config/normalconfig.gui
index 6381664f..305faa81 100644
--- a/mod/src/main/resources/assets/dungeonsguide/gui/config/normalconfig.gui
+++ b/mod/src/main/resources/assets/dungeonsguide/gui/config/normalconfig.gui
@@ -16,6 +16,7 @@
   ~ along with this program.  If not, see <https://www.gnu.org/licenses/>.
   -->
 
+<PopupManager>
 <align vAlign="CENTER" hAlign="CENTER">
     <ConstrainedBox maxWidth="700" maxHeight="500">
         <bgcolor backgroundColor="0xFF111111">
@@ -86,4 +87,5 @@
             </col>
         </bgcolor>
     </ConstrainedBox>
-</align>
\ No newline at end of file
+</align>
+</PopupManager>
\ No newline at end of file
diff --git a/mod/src/main/resources/assets/dungeonsguide/gui/config/parameter/boolean.gui b/mod/src/main/resources/assets/dungeonsguide/gui/config/parameter/boolean.gui
new file mode 100644
index 00000000..4fc0c1c0
--- /dev/null
+++ b/mod/src/main/resources/assets/dungeonsguide/gui/config/parameter/boolean.gui
@@ -0,0 +1,22 @@
+
+<!--
+  ~ 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/>.
+  -->
+
+<size width="40" height="14">
+        <SimpleToggleButton bind:enabled="enabled"/>
+</size>
\ No newline at end of file
diff --git a/mod/src/main/resources/assets/dungeonsguide/gui/config/parameter/color.gui b/mod/src/main/resources/assets/dungeonsguide/gui/config/parameter/color.gui
new file mode 100644
index 00000000..d5db4950
--- /dev/null
+++ b/mod/src/main/resources/assets/dungeonsguide/gui/config/parameter/color.gui
@@ -0,0 +1,25 @@
+
+<!--
+  ~ 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/>.
+  -->
+
+<size width="100" height="25">
+        <RoundButton on:click="setColor" hPadding="1"
+                     text=""
+                     bind:backgroundColor="color" bind:hoveredBackgroundColor="hover" bind:pressedBackgroundColor="click"
+        />
+</size>
\ No newline at end of file
diff --git a/mod/src/main/resources/assets/dungeonsguide/gui/config/parameter/colorSet.gui b/mod/src/main/resources/assets/dungeonsguide/gui/config/parameter/colorSet.gui
new file mode 100644
index 00000000..89129d84
--- /dev/null
+++ b/mod/src/main/resources/assets/dungeonsguide/gui/config/parameter/colorSet.gui
@@ -0,0 +1,85 @@
+<!--
+  ~ 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/>.
+  -->
+
+<size width="137" height="102">
+    <stack>
+        <padding left="7" top="7" right="7" bottom="7">
+            <col>
+                <flexible>
+                    <row>
+                        <aspectRatio width="1" height="1">
+                            <slot bind:child="colorWheel"/>
+                        </aspectRatio>
+                        <size width="5"/>
+                        <size width="15">
+                            <slot bind:child="valueBar"/>
+                        </size>
+                        <size width="5"/>
+                        <size width="15">
+                            <slot bind:child="alphaBar"/>
+                        </size>
+                        <size width="5"/>
+                        <size width="15">
+                            <slot bind:child="chromaBar"/>
+                        </size>
+                    </row>
+                </flexible>
+                <size height="5"/>
+                <size height="20">
+                    <TextField bind:value="color"/>
+                </size>
+            </col>
+        </padding>
+        <InvertStencil>
+            <RoundRect radius="10" backgroundColor="#FFFFFFFF">
+                <padding left="1" top="1" bottom="1" right="1">
+                    <RoundRect radius="10" backgroundColor="#FF111111">
+
+                    </RoundRect>
+                </padding>
+            </RoundRect>
+            <padding left="7" top="7" right="7" bottom="7" slot="stencil">
+                <col>
+                    <flexible>
+                        <row>
+                            <aspectRatio width="1" height="1">
+                                <size width="0" height="0"/>
+                            </aspectRatio>
+                            <size width="5"/>
+                            <size width="15">
+                                <size width="0" height="0"/>
+                            </size>
+                            <size width="5"/>
+                            <size width="15">
+                                <RoundRect radius="10" backgroundColor="#FFFFFFFF"/>
+                            </size>
+                            <size width="5"/>
+                            <size width="15">
+                                <size width="0" height="0"/>
+                            </size>
+                        </row>
+                    </flexible>
+                    <size height="5"/>
+                    <size height="20">
+                        <size width="0" height="0"/>
+                    </size>
+                </col>
+            </padding>
+        </InvertStencil>
+    </stack>
+</size>
\ No newline at end of file
diff --git a/mod/src/main/resources/assets/dungeonsguide/gui/config/parameter/keybind.gui b/mod/src/main/resources/assets/dungeonsguide/gui/config/parameter/keybind.gui
new file mode 100644
index 00000000..134d105e
--- /dev/null
+++ b/mod/src/main/resources/assets/dungeonsguide/gui/config/parameter/keybind.gui
@@ -0,0 +1,23 @@
+<!--
+  ~ 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/>.
+  -->
+
+<size width="100" height="25">
+    <RoundButton on:click="setKey" hPadding="1"
+                 bind:text="key"
+    />
+</size>
\ No newline at end of file
diff --git a/mod/src/main/resources/assets/dungeonsguide/gui/config/parameter/number.gui b/mod/src/main/resources/assets/dungeonsguide/gui/config/parameter/number.gui
new file mode 100644
index 00000000..57c21e3b
--- /dev/null
+++ b/mod/src/main/resources/assets/dungeonsguide/gui/config/parameter/number.gui
@@ -0,0 +1,46 @@
+<!--
+  ~ 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/>.
+  -->
+
+<size height="19">
+    <Stencil>
+        <row>
+            <aspectRatio width="1" height="1">
+                <ColorButton on:click="dec" hPadding="1"
+                             backgroundColor="#FF1C376E"          textColor="#FFFFFFFF"
+                             hoveredBackgroundColor="#FF1C5692"   hoveredTextColor="#FFFFFFFF"
+                             disabledBackgroundColor="0"  disabledTextColor="0"
+                             pressedBackgroundColor="#FF1D5F9C"   pressedTextColor="#FFFFFFFF"
+                             text="&lt;"
+                />
+            </aspectRatio>
+            <flexible>
+                <TextField bind:value="value"/>
+            </flexible>
+            <aspectRatio width="1" height="1">
+                <ColorButton on:click="inc" hPadding="1"
+                             backgroundColor="#FF1C376E"          textColor="#FFFFFFFF"
+                             hoveredBackgroundColor="#FF1C5692"   hoveredTextColor="#FFFFFFFF"
+                             disabledBackgroundColor="0"  disabledTextColor="0"
+                             pressedBackgroundColor="#FF1D5F9C"   pressedTextColor="#FFFFFFFF"
+                             text="&gt;"
+                />
+            </aspectRatio>
+        </row>
+        <CircularRect slot="stencil"/>
+    </Stencil>
+</size>
\ No newline at end of file
diff --git a/mod/src/main/resources/assets/dungeonsguide/gui/config/parameter/string.gui b/mod/src/main/resources/assets/dungeonsguide/gui/config/parameter/string.gui
new file mode 100644
index 00000000..fea9fe77
--- /dev/null
+++ b/mod/src/main/resources/assets/dungeonsguide/gui/config/parameter/string.gui
@@ -0,0 +1,22 @@
+
+<!--
+  ~ 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/>.
+  -->
+
+<size height="19">
+        <TextField bind:value="value"/>
+</size>
\ No newline at end of file
diff --git a/mod/src/main/resources/assets/dungeonsguide/gui/config/parameter/stringChoice.gui b/mod/src/main/resources/assets/dungeonsguide/gui/config/parameter/stringChoice.gui
new file mode 100644
index 00000000..27822ea9
--- /dev/null
+++ b/mod/src/main/resources/assets/dungeonsguide/gui/config/parameter/stringChoice.gui
@@ -0,0 +1,50 @@
+<!--
+  ~ 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/>.
+  -->
+
+<size height="19">
+    <Stencil>
+        <row>
+            <aspectRatio width="1" height="1">
+                <ColorButton on:click="dec" hPadding="1"
+                             backgroundColor="#FF1C376E"          textColor="#FFFFFFFF"
+                             hoveredBackgroundColor="#FF1C5692"   hoveredTextColor="#FFFFFFFF"
+                             disabledBackgroundColor="0"  disabledTextColor="0"
+                             pressedBackgroundColor="#FF1D5F9C"   pressedTextColor="#FFFFFFFF"
+                             text="&lt;"
+                />
+            </aspectRatio>
+            <flexible>
+                <bgcolor backgroundColor="#FF000000">
+                    <align hAlign="CENTER" vAlign="CENTER">
+                        <Text bind:text="value" color="#FFFFFFFF"/>
+                    </align>
+                </bgcolor>
+            </flexible>
+            <aspectRatio width="1" height="1">
+                <ColorButton on:click="inc" hPadding="1"
+                             backgroundColor="#FF1C376E"          textColor="#FFFFFFFF"
+                             hoveredBackgroundColor="#FF1C5692"   hoveredTextColor="#FFFFFFFF"
+                             disabledBackgroundColor="0"  disabledTextColor="0"
+                             pressedBackgroundColor="#FF1D5F9C"   pressedTextColor="#FFFFFFFF"
+                             text="&gt;"
+                />
+            </aspectRatio>
+        </row>
+        <CircularRect slot="stencil"/>
+    </Stencil>
+</size>
\ No newline at end of file
diff --git a/mod/src/main/resources/assets/dungeonsguide/gui/config/parameteritem.gui b/mod/src/main/resources/assets/dungeonsguide/gui/config/parameteritem.gui
new file mode 100644
index 00000000..cc8115f2
--- /dev/null
+++ b/mod/src/main/resources/assets/dungeonsguide/gui/config/parameteritem.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/>.
+  -->
+
+<padding left="5" right="5" top="5">
+    <col>
+        <line color="#FFFFFFFF"/>
+        <size width="0" height="5"/>
+        <IntrinsicHeight>
+            <row>
+                <SelectiveContainer bind:visible="iconVisibility">
+                    <aspectRatio width="1" height="1" slot="show">
+                        <Stencil>
+                            <ResourceImage bind:location="icon" width="128" height="128" textureWidth="128" textureHeight="128"/>
+                            <RoundRect radius="10" slot="stencil"/>
+                        </Stencil>
+                    </aspectRatio>
+                    <size width="0" height="0" slot="hide"/>
+                </SelectiveContainer>
+                <flexible>
+                    <col mainAlign="START" crossAlign="START">
+                        <padding left="5" right="5" top="5" bottom="5">
+                            <row crossAlign="END">
+                                <flexible>
+                                    <Text bind:text="name" color="#FFFFFFFF" size="12"/>
+                                </flexible>
+                            </row>
+                        </padding>
+                        <col crossAlign="START">
+                            <padding left="5" bottom="5" right="5" top="3">
+                                <Text bind:text="description" color="#FFAAAAAA"/>
+                            </padding>
+                        </col>
+                    </col>
+                </flexible>
+                <size width="150">
+                    <padding left="10" right="10" top="10" bottom="10">
+                        <align vAlign="CENTER" hAlign="CENTER">
+                            <slot bind:child="edit"/>
+                        </align>
+                    </padding>
+                </size>
+            </row>
+        </IntrinsicHeight>
+    </col>
+</padding>
\ No newline at end of file
diff --git a/mod/src/main/resources/assets/dungeonsguide/gui/config/popup/quickEdit.gui b/mod/src/main/resources/assets/dungeonsguide/gui/config/popup/quickEdit.gui
new file mode 100644
index 00000000..105a4680
--- /dev/null
+++ b/mod/src/main/resources/assets/dungeonsguide/gui/config/popup/quickEdit.gui
@@ -0,0 +1,23 @@
+<!--
+  ~ 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/>.
+  -->
+
+<size height="20">
+    <padding top="5">
+        <RoundButton text="Configure" on:click="configure"/>
+    </padding>
+</size>
\ No newline at end of file
diff --git a/mod/src/main/resources/assets/dungeonsguide/gui/config/popup/quickEnable.gui b/mod/src/main/resources/assets/dungeonsguide/gui/config/popup/quickEnable.gui
new file mode 100644
index 00000000..bdc3120d
--- /dev/null
+++ b/mod/src/main/resources/assets/dungeonsguide/gui/config/popup/quickEnable.gui
@@ -0,0 +1,34 @@
+<!--
+  ~ 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/>.
+  -->
+
+<size height="20">
+    <padding top="6">
+        <row>
+            <flexible>
+                <align vAlign="CENTER" hAlign="START">
+                    <Text text="Enable" color="#FFFFFFFF"/>
+                </align>
+            </flexible>
+            <size width="45" height="14">
+                <padding left="5">
+                    <SimpleToggleButton bind:enabled="enabled"/>
+                </padding>
+            </size>
+        </row>
+    </padding>
+</size>
\ No newline at end of file
diff --git a/mod/src/main/resources/assets/dungeonsguide/gui/config/popupmenu.gui b/mod/src/main/resources/assets/dungeonsguide/gui/config/popupmenu.gui
index ecfe8c5d..ec192ef4 100644
--- a/mod/src/main/resources/assets/dungeonsguide/gui/config/popupmenu.gui
+++ b/mod/src/main/resources/assets/dungeonsguide/gui/config/popupmenu.gui
@@ -16,7 +16,7 @@
   ~ along with this program.  If not, see <https://www.gnu.org/licenses/>.
   -->
 <UnconstrainedBox>
-        <ConstrainedBox maxWidth="200">
+        <ConstrainedBox maxWidth="150">
             <RoundRect radius="5" backgroundColor="#FF121212">
                 <padding top="5" bottom="5" left="5" right="5">
                     <col mainAlign="START" crossAlign="STRETCH" bind:_="items"/>
diff --git a/mod/src/main/resources/assets/dungeonsguide/gui/elements/locationedPopup.gui b/mod/src/main/resources/assets/dungeonsguide/gui/elements/locationedPopup.gui
index 9d56c62c..56732908 100644
--- a/mod/src/main/resources/assets/dungeonsguide/gui/elements/locationedPopup.gui
+++ b/mod/src/main/resources/assets/dungeonsguide/gui/elements/locationedPopup.gui
@@ -15,6 +15,10 @@
   ~ 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/>.
   -->
-    <absXY bind:x="x" bind:y="y">
-        <slot bind:child="child" bind:ref="ref"/>
-    </absXY>
\ No newline at end of file
+<absXY bind:x="x" bind:y="y">
+    <UnconstrainedBox>
+        <measure bind:size="size">
+            <slot bind:child="child" bind:ref="ref"/>
+        </measure>
+    </UnconstrainedBox>
+</absXY>
\ No newline at end of file
diff --git a/mod/src/main/resources/assets/dungeonsguide/gui/features/fairysoul/roomconfiguration.gui b/mod/src/main/resources/assets/dungeonsguide/gui/features/fairysoul/roomconfiguration.gui
new file mode 100644
index 00000000..c9bbbc54
--- /dev/null
+++ b/mod/src/main/resources/assets/dungeonsguide/gui/features/fairysoul/roomconfiguration.gui
@@ -0,0 +1,49 @@
+<!--
+  ~ 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/>.
+  -->
+
+<padding left="5" right="5" top="5">
+    <col>
+        <line color="#FFFFFFFF"/>
+        <size width="0" height="5"/>
+        <row crossAlign="END">
+            <flexible>
+                <Text text="Enable for these rooms" color="#FFFFFFFF" size="12"/>
+            </flexible>
+            <size width="60" height="12">
+                <padding left="5">
+                    <RoundButton on:click="eall" hPadding="1"
+                                 text="Enable All"
+                    />
+                </padding>
+            </size>
+            <size width="60" height="12">
+                <padding left="5">
+                    <RoundButton on:click="dall" hPadding="1"
+                                 text="Disable All"
+                    />
+                </padding>
+            </size>
+        </row>
+        <size width="0" height="5"/>
+        <RoundRect radius="5" backgroundColor="#FF333333">
+            <padding left="5" top="5" right="5" bottom="5">
+                <WrapGrid minimumWidth="160" gap="5" bind:_="rooms"/>
+            </padding>
+        </RoundRect>
+    </col>
+</padding>
\ No newline at end of file
diff --git a/mod/src/main/resources/assets/dungeonsguide/gui/features/fairysoul/roomswitch.gui b/mod/src/main/resources/assets/dungeonsguide/gui/features/fairysoul/roomswitch.gui
new file mode 100644
index 00000000..64352709
--- /dev/null
+++ b/mod/src/main/resources/assets/dungeonsguide/gui/features/fairysoul/roomswitch.gui
@@ -0,0 +1,34 @@
+<!--
+  ~ 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/>.
+  -->
+
+<size height="20">
+    <padding left="5" right="5">
+        <row crossAlign="CENTER">
+            <flexible>
+                <align vAlign="CENTER" hAlign="START">
+                    <Text bind:text="name" color="#FFFFFFFF"/>
+                </align>
+            </flexible>
+            <size width="45" height="14">
+                <padding left="5">
+                    <SimpleToggleButton bind:enabled="enabled"/>
+                </padding>
+            </size>
+        </row>
+    </padding>
+</size>
\ No newline at end of file
diff --git a/mod/src/main/resources/assets/dungeonsguide/shaders/chromacircle.frag b/mod/src/main/resources/assets/dungeonsguide/shaders/chromacircle.frag
new file mode 100644
index 00000000..25354550
--- /dev/null
+++ b/mod/src/main/resources/assets/dungeonsguide/shaders/chromacircle.frag
@@ -0,0 +1,27 @@
+#version 120
+
+#define TWO_PI 6.28318530718
+
+uniform float radius;
+uniform vec2 centerPos;
+uniform float smoothness;
+uniform float value;
+
+
+vec3 hsv2rgb(vec3 c) {
+    vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
+    vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
+    return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
+}
+
+void main() {
+    vec2 stuff = gl_FragCoord.xy - centerPos;
+    float sdf = length(stuff)-radius;
+    float saturation =  1.0+(sdf / radius);
+    float clampd = 1.0 - smoothstep(-smoothness, smoothness, sdf);
+    float angle = atan(-stuff.x, -stuff.y) / TWO_PI + 0.5;
+
+    vec3 col = hsv2rgb(vec3(angle, saturation, value));
+
+    gl_FragColor = vec4(col,clampd);
+}
\ No newline at end of file
diff --git a/mod/src/main/resources/assets/dungeonsguide/shaders/chromaroundrect.frag b/mod/src/main/resources/assets/dungeonsguide/shaders/chromaroundrect.frag
new file mode 100644
index 00000000..7ddf2db8
--- /dev/null
+++ b/mod/src/main/resources/assets/dungeonsguide/shaders/chromaroundrect.frag
@@ -0,0 +1,23 @@
+#version 120
+uniform float radius;
+uniform vec2 halfSize;
+uniform vec2 centerPos;
+uniform float smoothness;
+varying vec4 color;
+
+vec3 hsv2rgb(vec3 c)
+{
+    vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
+    vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
+    return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
+}
+
+float roundedBoxSDF(vec2 CenterPosition, vec2 Size, float Radius) {
+    return length(max(abs(CenterPosition)-Size+Radius,0.0))-Radius;
+}
+
+void main() {
+    float distance 		= roundedBoxSDF(gl_FragCoord.xy - centerPos, halfSize, radius);
+    float smoothedAlpha = smoothstep(-smoothness,0.0, -distance);
+    gl_FragColor = vec4(hsv2rgb(color.rgb), color.a) * vec4(1.0, 1.0, 1.0, smoothedAlpha);
+}
\ No newline at end of file
diff --git a/mod/src/main/resources/assets/dungeonsguide/shaders/chromaroundrect.vert b/mod/src/main/resources/assets/dungeonsguide/shaders/chromaroundrect.vert
new file mode 100644
index 00000000..377182c5
--- /dev/null
+++ b/mod/src/main/resources/assets/dungeonsguide/shaders/chromaroundrect.vert
@@ -0,0 +1,19 @@
+#version 120
+
+varying vec4 color;
+
+vec3 rgb2hsv(vec3 c)
+{
+    vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
+    vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
+    vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
+
+    float d = q.x - min(q.w, q.y);
+    float e = 1.0e-10;
+    return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
+}
+
+void main() {
+    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
+    color = vec4(rgb2hsv(gl_Color.rgb), gl_Color.a);
+}
\ No newline at end of file
diff --git a/mod/src/main/resources/assets/dungeonsguide/shaders/donut.frag b/mod/src/main/resources/assets/dungeonsguide/shaders/donut.frag
new file mode 100644
index 00000000..cca6bc39
--- /dev/null
+++ b/mod/src/main/resources/assets/dungeonsguide/shaders/donut.frag
@@ -0,0 +1,17 @@
+#version 120
+
+
+uniform float radius;
+uniform float thickness;
+uniform vec2 centerPos;
+uniform float smoothness;
+
+
+
+void main() {
+    vec2 stuff = gl_FragCoord.xy - centerPos;
+    float sdf = abs(length(stuff)-radius);
+    float clampd = 1.0 - smoothstep(thickness, thickness+smoothness, sdf);
+
+    gl_FragColor = gl_Color * vec4(1.0, 1.0, 1.0, clampd);
+}
\ No newline at end of file
diff --git a/mod/src/main/resources/assets/dungeonsguide/shaders/roundrect.frag b/mod/src/main/resources/assets/dungeonsguide/shaders/roundrect.frag
index 93a6c7c0..95649cf4 100644
--- a/mod/src/main/resources/assets/dungeonsguide/shaders/roundrect.frag
+++ b/mod/src/main/resources/assets/dungeonsguide/shaders/roundrect.frag
@@ -1,8 +1,10 @@
-#version 110
+#version 120
 uniform float radius;
 uniform vec2 halfSize;
 uniform vec2 centerPos;
 uniform float smoothness;
+varying vec4 color;
+
 
 float roundedBoxSDF(vec2 CenterPosition, vec2 Size, float Radius) {
     return length(max(abs(CenterPosition)-Size+Radius,0.0))-Radius;
@@ -11,5 +13,5 @@ float roundedBoxSDF(vec2 CenterPosition, vec2 Size, float Radius) {
 void main() {
     float distance 		= roundedBoxSDF(gl_FragCoord.xy - centerPos, halfSize, radius);
     float smoothedAlpha = smoothstep(-smoothness,0.0, -distance);
-    gl_FragColor = gl_Color * vec4(1.0, 1.0, 1.0, smoothedAlpha);
+    gl_FragColor = color * vec4(1.0, 1.0, 1.0, smoothedAlpha);
 }
\ No newline at end of file
diff --git a/mod/src/main/resources/assets/dungeonsguide/shaders/roundrect.vert b/mod/src/main/resources/assets/dungeonsguide/shaders/roundrect.vert
new file mode 100644
index 00000000..7a2ec153
--- /dev/null
+++ b/mod/src/main/resources/assets/dungeonsguide/shaders/roundrect.vert
@@ -0,0 +1,8 @@
+#version 120
+
+varying vec4 color;
+
+void main() {
+    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
+    color = gl_Color;
+}
\ No newline at end of file
-- 
cgit