From addd286756f2ed63c346881c0b2dacfb8b5ba273 Mon Sep 17 00:00:00 2001 From: radimous Date: Wed, 4 Dec 2024 16:14:45 +0000 Subject: [PATCH] cleanup --- .../com/radimous/vhatcaniroll/Config.java | 20 +- .../com/radimous/vhatcaniroll/Keybind.java | 2 + .../vhatcaniroll/ModifierListContainer.java | 54 ----- .../ScrollableTextInputElement.java | 30 --- .../radimous/vhatcaniroll/VHatCanIRoll.java | 57 ----- .../radimous/vhatcaniroll/logic/Items.java | 65 ++++++ .../{Helper.java => logic/Modifiers.java} | 208 +++++++++++------- ...StatisticsElementContainerScreenMixin.java | 2 +- .../{ => ui}/GearModifierScreen.java | 193 ++++++++-------- .../ui/ModifierListContainer.java | 77 +++++++ .../ui/ScrollableLvlInputElement.java | 72 ++++++ 11 files changed, 451 insertions(+), 329 deletions(-) delete mode 100644 src/main/java/com/radimous/vhatcaniroll/ModifierListContainer.java delete mode 100644 src/main/java/com/radimous/vhatcaniroll/ScrollableTextInputElement.java create mode 100644 src/main/java/com/radimous/vhatcaniroll/logic/Items.java rename src/main/java/com/radimous/vhatcaniroll/{Helper.java => logic/Modifiers.java} (56%) rename src/main/java/com/radimous/vhatcaniroll/{ => ui}/GearModifierScreen.java (69%) create mode 100644 src/main/java/com/radimous/vhatcaniroll/ui/ModifierListContainer.java create mode 100644 src/main/java/com/radimous/vhatcaniroll/ui/ScrollableLvlInputElement.java diff --git a/src/main/java/com/radimous/vhatcaniroll/Config.java b/src/main/java/com/radimous/vhatcaniroll/Config.java index 6e7b9ca..e8a62fb 100644 --- a/src/main/java/com/radimous/vhatcaniroll/Config.java +++ b/src/main/java/com/radimous/vhatcaniroll/Config.java @@ -10,6 +10,10 @@ public class Config { public static final ForgeConfigSpec.IntValue BUTTON_Y; public static final ForgeConfigSpec.BooleanValue COMBINE_LVL_TO_ABILITIES; public static final ForgeConfigSpec.IntValue MAX_LEVEL_OVERRIDE; + public static final ForgeConfigSpec.BooleanValue SHOW_ABILITY_ENHANCEMENTS; + public static final ForgeConfigSpec.BooleanValue SHOW_WEIGHT; + public static final ForgeConfigSpec.BooleanValue SHOW_CHANCE; + static { ForgeConfigSpec.Builder builder = new ForgeConfigSpec.Builder(); @@ -25,6 +29,8 @@ public class Config { BUTTON_X = builder .comment("x position of the button") .defineInRange("buttonPositionX", 5, Integer.MIN_VALUE, Integer.MAX_VALUE); + + //TODO: auto move the button to 130 if QOL Hunters is loaded (button conflict) BUTTON_Y = builder .comment("y position of the button") .defineInRange("buttonPositionY", 109, Integer.MIN_VALUE, Integer.MAX_VALUE); @@ -34,11 +40,23 @@ public class Config { ALLOW_DUPE = builder .comment("allow duplicate modifiers") .define("allowDupe", false); + builder.pop(); + MAX_LEVEL_OVERRIDE = builder .comment("override max level") .defineInRange("maxLevelOverride", -1, -1, Integer.MAX_VALUE); - builder.pop(); + SHOW_ABILITY_ENHANCEMENTS = builder + .comment("show ability enhancements") + .define("showAbilityEnhancements", false); + + SHOW_WEIGHT = builder + .comment("show weight") + .define("showWeight", false); + + SHOW_CHANCE = builder + .comment("show chance") + .define("showChance", true); SPEC = builder.build(); } } diff --git a/src/main/java/com/radimous/vhatcaniroll/Keybind.java b/src/main/java/com/radimous/vhatcaniroll/Keybind.java index b2c9d90..d5cfd56 100644 --- a/src/main/java/com/radimous/vhatcaniroll/Keybind.java +++ b/src/main/java/com/radimous/vhatcaniroll/Keybind.java @@ -1,6 +1,8 @@ package com.radimous.vhatcaniroll; import com.mojang.blaze3d.platform.InputConstants; +import com.radimous.vhatcaniroll.ui.GearModifierScreen; + import net.minecraft.client.KeyMapping; import net.minecraft.client.Minecraft; import net.minecraftforge.api.distmarker.Dist; diff --git a/src/main/java/com/radimous/vhatcaniroll/ModifierListContainer.java b/src/main/java/com/radimous/vhatcaniroll/ModifierListContainer.java deleted file mode 100644 index 010a6e8..0000000 --- a/src/main/java/com/radimous/vhatcaniroll/ModifierListContainer.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.radimous.vhatcaniroll; - -import iskallia.vault.client.gui.framework.ScreenTextures; -import iskallia.vault.client.gui.framework.element.LabelElement; -import iskallia.vault.client.gui.framework.element.VerticalScrollClipContainer; -import iskallia.vault.client.gui.framework.spatial.Padding; -import iskallia.vault.client.gui.framework.spatial.Spatials; -import iskallia.vault.client.gui.framework.spatial.spi.ISpatial; -import iskallia.vault.client.gui.framework.text.LabelTextStyle; -import iskallia.vault.config.gear.VaultGearTierConfig; -import net.minecraft.ChatFormatting; -import net.minecraft.network.chat.TextComponent; - -import java.util.Optional; - -public class ModifierListContainer extends VerticalScrollClipContainer { - - public ModifierListContainer(ISpatial spatial, GearModifierScreen parent) { - super(spatial, Padding.ZERO, ScreenTextures.INSET_BLACK_BACKGROUND); - int i = 20; - int k = 9; - boolean legendary = parent.isLegendary(); - Optional optCfg = VaultGearTierConfig.getConfig(parent.getCurrGear()); - LabelElement itemName = new LabelElement<>( - Spatials.positionXY(k, 5).width(this.innerWidth() - k).height(15), new TextComponent( - parent.getCurrGear().getItem().toString().toUpperCase() + " - LVL " + parent.getCurrLvl()) - .withStyle(ChatFormatting.UNDERLINE).withStyle(legendary ? ChatFormatting.GOLD : ChatFormatting.WHITE), LabelTextStyle.defaultStyle() - ); - this.addElement(itemName); - if (optCfg.isPresent()) { - VaultGearTierConfig cfg = optCfg.get(); - for (var modifier : Helper.getModifierList(parent.getCurrLvl(), cfg, legendary)) { - LabelElement labelelement = new LabelElement<>( - Spatials.positionXY(k, i).width(this.innerWidth() - k).height(15), modifier, LabelTextStyle.defaultStyle() - ); - this.addElement(labelelement); - i += 10; - } - } else { - LabelElement labelelement = new LabelElement<>( - Spatials.positionXY(k, i).width(this.innerWidth() - k).height(15), new TextComponent( - parent.getCurrGear().getItem() + " not found"), LabelTextStyle.defaultStyle() - ); - this.addElement(labelelement); - } - } - public float getScroll() { - return this.verticalScrollBarElement.getValue(); - } - - public void setScroll(float scroll) { - this.verticalScrollBarElement.setValue(scroll); - } -} \ No newline at end of file diff --git a/src/main/java/com/radimous/vhatcaniroll/ScrollableTextInputElement.java b/src/main/java/com/radimous/vhatcaniroll/ScrollableTextInputElement.java deleted file mode 100644 index ab42dc8..0000000 --- a/src/main/java/com/radimous/vhatcaniroll/ScrollableTextInputElement.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.radimous.vhatcaniroll; - -import iskallia.vault.client.gui.framework.element.TextInputElement; -import iskallia.vault.client.gui.framework.spatial.spi.ISpatial; -import net.minecraft.client.gui.Font; - -public class ScrollableTextInputElement extends TextInputElement { - public ScrollableTextInputElement(ISpatial spatial, Font font) { - super(spatial, font); - } - - @Override - public boolean onMouseScrolled(double mouseX, double mouseY, double delta) { - if (this.isMouseOver(mouseX, mouseY)) { - int val = parseInt(this.getInput()); - val += delta > 0 ? 1 : -1; - this.setInput(String.valueOf(val)); - return true; - } - return super.onMouseScrolled(mouseX, mouseY, delta); - } - - private int parseInt(String val) { - try { - return Integer.parseInt(val); - } catch (NumberFormatException e) { - return 0; - } - } -} diff --git a/src/main/java/com/radimous/vhatcaniroll/VHatCanIRoll.java b/src/main/java/com/radimous/vhatcaniroll/VHatCanIRoll.java index 003bfda..072907b 100644 --- a/src/main/java/com/radimous/vhatcaniroll/VHatCanIRoll.java +++ b/src/main/java/com/radimous/vhatcaniroll/VHatCanIRoll.java @@ -1,73 +1,16 @@ package com.radimous.vhatcaniroll; -import iskallia.vault.init.ModItems; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fml.ModLoadingContext; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.config.ModConfig; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - @Mod("vhatcaniroll") public class VHatCanIRoll { public static final String MODID = "vhatcaniroll"; - private static final List GEAR_ITEMS = new ArrayList<>(); public VHatCanIRoll() { ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, Config.SPEC); MinecraftForge.EVENT_BUS.register(this); } - - public static List getVaultGearItems() { - if (GEAR_ITEMS.isEmpty()){ - GEAR_ITEMS.addAll(List.of( - new ItemStack(ModItems.SWORD), - new ItemStack(ModItems.AXE), - new ItemStack(ModItems.HELMET), - new ItemStack(ModItems.CHESTPLATE), - new ItemStack(ModItems.LEGGINGS), - new ItemStack(ModItems.BOOTS), - new ItemStack(ModItems.FOCUS), - new ItemStack(ModItems.SHIELD), - new ItemStack(ModItems.WAND), - new ItemStack(ModItems.MAGNET), - new ItemStack(ModItems.JEWEL) - ) - ); - GEAR_ITEMS.addAll(getWoldGearItems()); - - } - return Collections.unmodifiableList(GEAR_ITEMS); - } - - public static List getWoldGearItems() { - List woldItems = new ArrayList<>(); - List woldItemFields = Arrays.asList( - "BATTLESTAFF", - "TRIDENT", - "PLUSHIE", - "LOOT_SACK" - ); - try{ - Class wold = Class.forName("xyz.iwolfking.woldsvaults.init.ModItems"); - for (String name : woldItemFields) { - try { - Item item = (Item) wold.getField(name).get(null); - woldItems.add(new ItemStack(item)); - } catch (IllegalArgumentException | SecurityException | NoSuchFieldException | - IllegalAccessException ignored) { - // no-op - } - } - } catch (ClassNotFoundException ignored) { - // no-op - } - return woldItems; - - } } diff --git a/src/main/java/com/radimous/vhatcaniroll/logic/Items.java b/src/main/java/com/radimous/vhatcaniroll/logic/Items.java new file mode 100644 index 0000000..97bef78 --- /dev/null +++ b/src/main/java/com/radimous/vhatcaniroll/logic/Items.java @@ -0,0 +1,65 @@ +package com.radimous.vhatcaniroll.logic; + +import iskallia.vault.init.ModItems; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +public class Items { + + private static final List GEAR_ITEMS = new ArrayList<>(); + + + public static List getVaultGearItems() { + if (GEAR_ITEMS.isEmpty()){ + GEAR_ITEMS.addAll(getVHGearItems()); + GEAR_ITEMS.addAll(getWoldGearItems()); + } + return Collections.unmodifiableList(GEAR_ITEMS); + } + + public static List getVHGearItems() { + return List.of( + new ItemStack(ModItems.SWORD), + new ItemStack(ModItems.AXE), + new ItemStack(ModItems.HELMET), + new ItemStack(ModItems.CHESTPLATE), + new ItemStack(ModItems.LEGGINGS), + new ItemStack(ModItems.BOOTS), + new ItemStack(ModItems.FOCUS), + new ItemStack(ModItems.SHIELD), + new ItemStack(ModItems.WAND), + new ItemStack(ModItems.MAGNET), + new ItemStack(ModItems.JEWEL) + ); + } + + public static List getWoldGearItems() { + List woldItems = new ArrayList<>(); + List woldItemFields = Arrays.asList( + "BATTLESTAFF", + "TRIDENT", + "PLUSHIE", + "LOOT_SACK" + ); + try{ + Class woldItemClass = Class.forName("xyz.iwolfking.woldsvaults.init.ModItems"); + for (String woldFieldName : woldItemFields) { + try { + Item item = (Item) woldItemClass.getField(woldFieldName).get(null); + woldItems.add(new ItemStack(item)); + } catch (IllegalArgumentException | SecurityException | NoSuchFieldException | + IllegalAccessException ignored) { + // no-op + } + } + } catch (ClassNotFoundException ignored) { + // no-op + } + return woldItems; + + } +} diff --git a/src/main/java/com/radimous/vhatcaniroll/Helper.java b/src/main/java/com/radimous/vhatcaniroll/logic/Modifiers.java similarity index 56% rename from src/main/java/com/radimous/vhatcaniroll/Helper.java rename to src/main/java/com/radimous/vhatcaniroll/logic/Modifiers.java index 7b1c3cc..cc87747 100644 --- a/src/main/java/com/radimous/vhatcaniroll/Helper.java +++ b/src/main/java/com/radimous/vhatcaniroll/logic/Modifiers.java @@ -1,5 +1,6 @@ -package com.radimous.vhatcaniroll; +package com.radimous.vhatcaniroll.logic; +import com.radimous.vhatcaniroll.Config; import com.radimous.vhatcaniroll.mixin.EffectConfigAccessor; import com.radimous.vhatcaniroll.mixin.VaultGearTierConfigAccessor; import iskallia.vault.config.gear.VaultGearTierConfig; @@ -10,7 +11,6 @@ import iskallia.vault.gear.attribute.config.BooleanFlagGenerator; import iskallia.vault.gear.attribute.config.ConfigurableAttributeGenerator; import iskallia.vault.gear.attribute.custom.effect.EffectGearAttribute; import iskallia.vault.init.ModConfigs; -import iskallia.vault.util.TextComponentUtils; import net.minecraft.ChatFormatting; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; @@ -24,42 +24,59 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.stream.Collectors; -public class Helper { +/** + * This is responsible for all the logic of transforming vh config -> list of components needed for the UI + */ +public class Modifiers { private static final ChatFormatting[] COLORS = new ChatFormatting[]{ChatFormatting.RED, ChatFormatting.GREEN, ChatFormatting.BLUE, ChatFormatting.YELLOW, ChatFormatting.LIGHT_PURPLE, ChatFormatting.AQUA, ChatFormatting.WHITE}; - public static List getModifierList(int lvl, VaultGearTierConfig cfg, boolean legendary) { - Map modifierGroup = - ((VaultGearTierConfigAccessor) cfg).getModifierGroup(); + public static List getModifierList(int lvl, VaultGearTierConfig cfg, int tierIncrease) { + Map modifierGroup = ((VaultGearTierConfigAccessor) cfg).getModifierGroup(); + ArrayList modList = new ArrayList<>(); + for (VaultGearTierConfig.ModifierAffixTagGroup affixTagGroup : modifierGroup.keySet()) { - processAffixTagGroup(lvl, affixTagGroup, modifierGroup, modList, legendary); + modList.addAll(getAffixGroupComponents(lvl, affixTagGroup, modifierGroup, tierIncrease)); } + return modList; } - private static void processAffixTagGroup(int lvl, VaultGearTierConfig.ModifierAffixTagGroup affixTagGroup, + private static List getAffixGroupComponents(int lvl, VaultGearTierConfig.ModifierAffixTagGroup affixTagGroup, Map modifierGroup, - ArrayList modList, boolean legendary) { - if (affixTagGroup.equals(VaultGearTierConfig.ModifierAffixTagGroup.ABILITY_ENHANCEMENT)) { - return; + int tierIncrease) { + + ArrayList componentList = new ArrayList<>(); + if (!Config.SHOW_ABILITY_ENHANCEMENTS.get() && affixTagGroup.equals(VaultGearTierConfig.ModifierAffixTagGroup.ABILITY_ENHANCEMENT)) { + return componentList; } if (modifierGroup.get(affixTagGroup).isEmpty()) { - return; + return componentList; } - modList.add(new TextComponent(affixTagGroup.toString().replace("_", " ")).withStyle(ChatFormatting.BOLD)); + componentList.add(new TextComponent(affixTagGroup.toString().replace("_", " ")).withStyle(ChatFormatting.BOLD)); - Map groupCounts = countGroups(lvl, affixTagGroup, modifierGroup, legendary); + int totalWeight = modifierGroup.get(affixTagGroup).stream() + .mapToInt(x -> getModifierTiers(lvl, x).stream().mapToInt(VaultGearTierConfig.ModifierTier::getWeight).sum()) + .sum(); + if (Config.SHOW_WEIGHT.get()) { + componentList.add(new TextComponent("Total Weight: " + totalWeight).withStyle(ChatFormatting.BOLD)); + } + + + Map groupCounts = countGroups(lvl, affixTagGroup, modifierGroup, tierIncrease); Map> groupedModifiers = new HashMap<>(); for (VaultGearTierConfig.ModifierTierGroup modifierTierGroup : modifierGroup.get(affixTagGroup)) { ArrayList> mTierList; - if (legendary) { - mTierList = getLegendaryModifierTiers(lvl, modifierTierGroup); + + // TODO: support greater modifiers (greater is +1 tier, legendary is +2 tiers) (look how VH does it) + // maybe ENUM - NORMAL, GREATER, LEGENDARY and the button would cycle through them + if (tierIncrease > 0) { + mTierList = getIncreasedModifierTiers(lvl, modifierTierGroup, tierIncrease); } else { mTierList = getModifierTiers(lvl, modifierTierGroup); } @@ -68,9 +85,9 @@ public class Helper { continue; } String modGr = modifierTierGroup.getModifierGroup(); - Component newMod = getVal( - Objects.requireNonNull(VaultGearAttributeRegistry.getAttribute(modifierTierGroup.getAttribute())), - mTierList); + + + Component newMod = getModifierComponent(VaultGearAttributeRegistry.getAttribute(modifierTierGroup.getAttribute()),mTierList); if (groupCounts.get(modGr) > 1) { groupedModifiers.computeIfAbsent(modGr, k -> new ArrayList<>()).add(newMod); continue; @@ -79,35 +96,44 @@ public class Helper { MutableComponent full = new TextComponent(" "); full.append(newMod); - if (Config.ALLOW_DUPE.get() || !(modList.get(modList.size() - 1).getString()).equals(full.getString())) { //dumb way to fix ability lvl+ duplication - modList.add(full); + + int weight = modTierListWeight(mTierList); + if (Config.SHOW_WEIGHT.get()) { + full.append(" w"+weight); + } + + if (Config.SHOW_CHANCE.get()) { + full.append(String.format(" %.2f %%", ((double) weight * 100 / totalWeight))); + } + + if (Config.ALLOW_DUPE.get() || !(componentList.get(componentList.size() - 1).getString()).equals(full.getString())) { //dumb way to fix ability lvl+ duplication + componentList.add(full); } } - boolean useNums = false; - if (groupedModifiers.size() > COLORS.length) { - // more than 7 groups is a bit crazy, but just in case - useNums = true; - } + + // more than 7 groups is a bit crazy, but just in case + boolean useNums = groupedModifiers.size() > COLORS.length; int i = 0; for (var modGr: groupedModifiers.values()) { for (var mod: modGr) { MutableComponent full = new TextComponent(useNums ? i + " " : "► ").withStyle(COLORS[i % COLORS.length]); full.append(mod); - modList.add(full); + componentList.add(full); } i++; } - modList.add(TextComponent.EMPTY); + componentList.add(TextComponent.EMPTY); + return componentList; } private static Map countGroups(int lvl, VaultGearTierConfig.ModifierAffixTagGroup affixTagGroup, Map modifierGroup, - boolean legendary) { + int tierIncrease) { Map groupCounts = new HashMap<>(); for (VaultGearTierConfig.ModifierTierGroup modifierTierGroup : modifierGroup.get(affixTagGroup)) { ArrayList> mTierList; - if (legendary) { - mTierList = getLegendaryModifierTiers(lvl, modifierTierGroup); + if (tierIncrease > 0) { + mTierList = getIncreasedModifierTiers(lvl, modifierTierGroup, tierIncrease); } else { mTierList = getModifierTiers(lvl, modifierTierGroup); } @@ -120,15 +146,16 @@ public class Helper { return groupCounts; } - private static ArrayList> getLegendaryModifierTiers(int lvl, - VaultGearTierConfig.ModifierTierGroup modifierTierGroup) { + //TODO: check how noLegendary works in VH + private static ArrayList> getIncreasedModifierTiers(int lvl, + VaultGearTierConfig.ModifierTierGroup modifierTierGroup, int tierIncrease) { var res = new ArrayList>(); var highest = modifierTierGroup.getHighestForLevel(lvl); if (highest == null) { return res; // empty } - int index = Math.min(highest.getModifierTier() + 2, modifierTierGroup.size() - 1); + int index = Math.min(highest.getModifierTier() + tierIncrease, modifierTierGroup.size() - 1); var legendTier = modifierTierGroup.get(index); if (legendTier == null || legendTier.getWeight() == 0){ return res; // empty @@ -149,20 +176,23 @@ public class Helper { .collect(Collectors.toCollection(ArrayList::new)); } - // TODO: wtf is this, fix variable names and make it readable - // I don't think proper generics are possible, VaultGearTierConfig#getModifiersForLevel returns List> - private static Component getVal(VaultGearAttribute atr, - ArrayList> val) { - if (val.isEmpty()) { - return new TextComponent("ERR - EMPTY VAL"); + @SuppressWarnings("unchecked") // I don't think proper generics are possible, VaultGearTierConfig#getModifiersForLevel returns List> + private static Component getModifierComponent(VaultGearAttribute atr, + ArrayList> modifierTiers) { + if (modifierTiers.isEmpty()) { + return new TextComponent("ERR - EMPTY MODIFIER TIERS"); } + + if (atr == null) { + return new TextComponent("ERR - NULL ATTRIBUTE"); + } + ConfigurableAttributeGenerator atrGenerator = (ConfigurableAttributeGenerator) atr.getGenerator(); if (atrGenerator == null) { - return new TextComponent("ERR - NULL GENERATOR"); + return new TextComponent("ERR - NULL ATTRIBUTE GENERATOR"); } - C minConfig = (C) val.get(0).getModifierConfiguration(); - C maxConfig = (C) val.get(val.size() - 1).getModifierConfiguration(); - MutableComponent res; + C minConfig = (C) modifierTiers.get(0).getModifierConfiguration(); + C maxConfig = (C) modifierTiers.get(modifierTiers.size() - 1).getModifierConfiguration(); ResourceLocation atrRegName = atr.getRegistryName(); if (atrRegName == null) { return new TextComponent("ERR - NULL REGISTRY NAME"); @@ -170,18 +200,44 @@ public class Helper { String atrName = atrRegName.toString(); var minConfigDisplay = atrGenerator.getConfigDisplay(atr.getReader(), minConfig); - var maxConfigDisplay = atrGenerator.getConfigDisplay(atr.getReader(), maxConfig); + + MutableComponent res = null; + if (modifierTiers.size() > 1) { + res = rangeComponent(atrName, atr, atrGenerator, minConfig, maxConfig); + } + if (res == null && minConfigDisplay != null) { + res = minConfigDisplay.withStyle(atr.getReader().getColoredTextStyle()); + if (minConfig instanceof AbilityLevelAttribute.Config minConfigAbility) { + return abilityLvlComponent(res, atr, minConfigAbility); + } + + if (minConfig instanceof EffectGearAttribute.Config ) { + return minConfigDisplay; + } + return res; + } + return new TextComponent("ERR - NULL DISPLAY " + atrName); + } + + /** + * This method handles combining multiple configs into a single component + * VH doesn't have method for this, so we need to do it manually + * it is using the same logic as VH does when shifting on gear piece to get the range + * and combining it with normal display for single component (that has name and color) + */ + private static MutableComponent rangeComponent(String atrName, VaultGearAttribute atr, + ConfigurableAttributeGenerator atrGenerator, C minConfig, C maxConfig) { + MutableComponent res = atrGenerator.getConfigRangeDisplay(atr.getReader(), minConfig, maxConfig); + var minConfigDisplay = atrGenerator.getConfigDisplay(atr.getReader(), minConfig); + var maxConfigDisplay = atrGenerator.getConfigDisplay(atr.getReader(), maxConfig); - if (val.size() > 1) { - // range - res = atrGenerator.getConfigRangeDisplay(atr.getReader(), minConfig, maxConfig); if (res != null && minConfig instanceof AbilityLevelAttribute.Config minConfigAbility) { return abilityLvlComponent(res, atr, minConfigAbility); } - if (res != null && atrName.equals("the_vault:wendarr_affinity")) { - return res.append(" God Affinity").withStyle(atr.getReader().getColoredTextStyle()); - } + + //FIXME: poison avoidance was changed to single generic "Effect Avoidance" and it's not working + //FIXME: clouds with roman numerals are not working if (atrName.equals("the_vault:effect_avoidance") && minConfigDisplay != null) { // res -> "30% - 50%" // single -> "30% Poison Avoidance" @@ -204,40 +260,32 @@ public class Helper { if (res != null) { return atr.getReader().formatConfigDisplay(LogicalSide.CLIENT, res); } - } - if (minConfigDisplay != null) { - res = minConfigDisplay.withStyle(atr.getReader().getColoredTextStyle()); - if (minConfig instanceof AbilityLevelAttribute.Config minConfigAbility) { - return abilityLvlComponent(res, atr, minConfigAbility); - } - if (atrName.equals("the_vault:wendarr_affinity")) { - return TextComponentUtils.replace(TextComponentUtils.createSourceStack(LogicalSide.CLIENT), res, - "Wendarr Affinity", new TextComponent("God Affinity")) - .withStyle(atr.getReader().getColoredTextStyle()); - } - if (minConfig instanceof EffectGearAttribute.Config ) { - return minConfigDisplay; - } return res; - } - return new TextComponent("ERR - NULL DISPLAY " + atrName); } - private static Component abilityLvlComponent(MutableComponent res, VaultGearAttribute atr, + + private static MutableComponent abilityLvlComponent(MutableComponent res, VaultGearAttribute atr, AbilityLevelAttribute.Config minConfig) { if (Config.COMBINE_LVL_TO_ABILITIES.get()) { return res.append(" added ability levels").withStyle(atr.getReader().getColoredTextStyle()); - } else { - var abComp = new TextComponent("+").withStyle(atr.getReader().getColoredTextStyle()); - var optSkill = ModConfigs.ABILITIES.getAbilityById(minConfig.getAbilityKey()); - if (optSkill.isEmpty()) { - return res.append(" added ability levels").withStyle(atr.getReader().getColoredTextStyle()); - } - var abName = optSkill.get().getName(); - abComp.append(res); - abComp.append(" to level of "); - abComp.append(new TextComponent(abName).withStyle(Style.EMPTY.withColor(14076214))); - return abComp; } + + var abComp = new TextComponent("+").withStyle(atr.getReader().getColoredTextStyle()); + var optSkill = ModConfigs.ABILITIES.getAbilityById(minConfig.getAbilityKey()); + if (optSkill.isEmpty()) { + return res.append(" added ability levels").withStyle(atr.getReader().getColoredTextStyle()); + } + var abName = optSkill.get().getName(); + abComp.append(res); + abComp.append(" to level of "); + abComp.append(new TextComponent(abName).withStyle(Style.EMPTY.withColor(14076214))); + return abComp; + } + + private static int modTierListWeight(List> val) { + if (val == null || val.isEmpty()) { + return 0; + } + return val.stream().mapToInt(VaultGearTierConfig.ModifierTier::getWeight).sum(); } } diff --git a/src/main/java/com/radimous/vhatcaniroll/mixin/StatisticsElementContainerScreenMixin.java b/src/main/java/com/radimous/vhatcaniroll/mixin/StatisticsElementContainerScreenMixin.java index b7bb21b..df319e2 100644 --- a/src/main/java/com/radimous/vhatcaniroll/mixin/StatisticsElementContainerScreenMixin.java +++ b/src/main/java/com/radimous/vhatcaniroll/mixin/StatisticsElementContainerScreenMixin.java @@ -1,7 +1,7 @@ package com.radimous.vhatcaniroll.mixin; import com.radimous.vhatcaniroll.Config; -import com.radimous.vhatcaniroll.GearModifierScreen; +import com.radimous.vhatcaniroll.ui.GearModifierScreen; import iskallia.vault.client.gui.framework.ScreenTextures; import iskallia.vault.client.gui.framework.element.ButtonElement; import iskallia.vault.client.gui.framework.element.FakeItemSlotElement; diff --git a/src/main/java/com/radimous/vhatcaniroll/GearModifierScreen.java b/src/main/java/com/radimous/vhatcaniroll/ui/GearModifierScreen.java similarity index 69% rename from src/main/java/com/radimous/vhatcaniroll/GearModifierScreen.java rename to src/main/java/com/radimous/vhatcaniroll/ui/GearModifierScreen.java index 1fd22f8..eaabd6f 100644 --- a/src/main/java/com/radimous/vhatcaniroll/GearModifierScreen.java +++ b/src/main/java/com/radimous/vhatcaniroll/ui/GearModifierScreen.java @@ -1,6 +1,9 @@ -package com.radimous.vhatcaniroll; +package com.radimous.vhatcaniroll.ui; import com.mojang.blaze3d.platform.InputConstants; +import com.radimous.vhatcaniroll.Config; +import com.radimous.vhatcaniroll.logic.Items; + import iskallia.vault.client.gui.framework.ScreenRenderers; import iskallia.vault.client.gui.framework.ScreenTextures; import iskallia.vault.client.gui.framework.element.FakeItemSlotElement; @@ -8,7 +11,6 @@ import iskallia.vault.client.gui.framework.element.LabelElement; import iskallia.vault.client.gui.framework.element.NineSliceButtonElement; import iskallia.vault.client.gui.framework.element.NineSliceElement; import iskallia.vault.client.gui.framework.element.TabElement; -import iskallia.vault.client.gui.framework.element.TextInputElement; import iskallia.vault.client.gui.framework.element.TextureAtlasElement; import iskallia.vault.client.gui.framework.element.spi.ILayoutStrategy; import iskallia.vault.client.gui.framework.render.ScreenTooltipRenderer; @@ -18,8 +20,6 @@ import iskallia.vault.client.gui.framework.spatial.Spatials; import iskallia.vault.client.gui.framework.spatial.spi.IPosition; import iskallia.vault.client.gui.framework.spatial.spi.ISpatial; import iskallia.vault.client.gui.framework.text.LabelTextStyle; -import iskallia.vault.client.gui.overlay.VaultBarOverlay; -import iskallia.vault.init.ModConfigs; import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; import net.minecraft.network.chat.TextComponent; @@ -30,11 +30,11 @@ import java.util.ArrayList; import java.util.List; public class GearModifierScreen extends AbstractElementScreen { - //TODO: code cleanup - variable naming, magic numbers, some logic reordering etc + //TODO: remove magic numbers private ModifierListContainer modifierList; - private final TextInputElement lvlInput; - private boolean legendary; + private final ScrollableLvlInputElement lvlInput; + private int tierIncrease = 0; private LabelElement legendaryLabel; private int currIndex = 0; @@ -68,62 +68,69 @@ public class GearModifierScreen extends AbstractElementScreen { createTabs(); this.lvlInput = this.addElement(createLvlInput()); - createLvlButtons(); + + createLvlButtons(lvlInput); createLegendaryButton(); // inner black window - this.modifierList = new ModifierListContainer( - Spatials.positionXY(7, 50).size(this.getGuiSpatial().width() - 14, this.getGuiSpatial().height() - 57), - this) - .layout(this.translateWorldSpatial()); + ISpatial modListSpatial = Spatials.positionXY(7, 50).size(this.getGuiSpatial().width() - 14, this.getGuiSpatial().height() - 57); + this.modifierList = new ModifierListContainer(modListSpatial, lvlInput.getValue(), tierIncrease, getCurrGear()).layout(this.translateWorldSpatial()); this.addElement(this.modifierList); } + // helper methods + public ItemStack getCurrGear() { - return VHatCanIRoll.getVaultGearItems().get(currIndex); - } - - public int getCurrLvl() { - try { - return Integer.parseInt(this.lvlInput.getInput()); - } catch (NumberFormatException e) { - return 0; - } - } - - private void increaseLvl() { - this.lvlInput.setInput(String.valueOf(this.getCurrLvl() + 1)); - } - - private void decreaseLvl() { - this.lvlInput.setInput(String.valueOf(this.getCurrLvl() - 1)); + return Items.getVaultGearItems().get(currIndex); } + /** + * Update the modifier list with the current gear item and lvl and legendary flag + * @param keepScroll whether to keep the current scroll position + */ private void updateModifierList(boolean keepScroll) { var oldScroll = this.modifierList.getScroll(); + this.removeElement(this.modifierList); - this.modifierList = new ModifierListContainer( - Spatials.positionXY(7, 50).size(this.getGuiSpatial().width() - 14, this.getGuiSpatial().height() - 57), - this) - .layout(this.translateWorldSpatial()); + ISpatial modListSpatial = Spatials.positionXY(7, 50).size(this.getGuiSpatial().width() - 14, this.getGuiSpatial().height() - 57); + this.modifierList = new ModifierListContainer(modListSpatial, lvlInput.getValue(), tierIncrease, getCurrGear()).layout(this.translateWorldSpatial()); + if (keepScroll) { this.modifierList.setScroll(oldScroll); } + this.addElement(this.modifierList); ScreenLayout.requestLayout(); } + // pulled from QuestOverviewElementScreen private ILayoutStrategy translateWorldSpatial() { return (screen, gui, parent, world) -> world.translateXY(this.getGuiSpatial()); } - private IPosition getPos(int tabIndex, boolean selected) { - if (tabIndex < 11){ + + // tabs + + /** + * Get the position where tab should be drawn + * @param tabIndex + * @param selected + * @return + */ + private IPosition getTabPos(int tabIndex, boolean selected) { + if (tabIndex < 11){ // top tabs return Spatials.positionXY(5 + tabIndex * 30, 2 + (selected ? 0 : 4)); } - return Spatials.positionXY(337 + (selected? 0:3), 35 + (tabIndex-11) * 30); + // right tabs (only needed for wold's rn) + return Spatials.positionXY(337 + (selected ? 0:3), 35 + (tabIndex-11) * 30); } + + /** + * Get the position where item "icon" should be drawn + * @param tabIndex + * @return + */ private ISpatial getItemPos(int tabIndex) { if (tabIndex < 11){ return Spatials.positionXY(10 + tabIndex * 30, 11); @@ -131,16 +138,17 @@ public class GearModifierScreen extends AbstractElementScreen { return Spatials.positionXY(342, 40 + (tabIndex-11) * 30); } - // actual tab + private TabElement getTabElement(int tabIndex, boolean selected) { - if (tabIndex < 11){ - return new TabElement<>(getPos(tabIndex, selected), + if (tabIndex < 11){ // top tabs + return new TabElement<>(getTabPos(tabIndex, selected), new TextureAtlasElement<>( selected ? ScreenTextures.TAB_BACKGROUND_TOP_SELECTED : ScreenTextures.TAB_BACKGROUND_TOP), new TextureAtlasElement<>(ScreenTextures.EMPTY), () -> switchTab(tabIndex)) .layout(this.translateWorldSpatial()); } - return new TabElement<>(getPos(tabIndex, selected), + + return new TabElement<>(getTabPos(tabIndex, selected), // right tabs (only needed for wold's rn) new TextureAtlasElement<>( selected ? ScreenTextures.TAB_BACKGROUND_RIGHT_SELECTED : ScreenTextures.TAB_BACKGROUND_RIGHT), new TextureAtlasElement<>(ScreenTextures.EMPTY), () -> switchTab(tabIndex)) @@ -148,7 +156,7 @@ public class GearModifierScreen extends AbstractElementScreen { } private void switchTab(int tabIndex) { - for (int i = 0; i < VHatCanIRoll.getVaultGearItems().size(); i++) { + for (int i = 0; i < Items.getVaultGearItems().size(); i++) { this.removeElement(tabs.get(i)); TabElement tab = getTabElement(i, i == tabIndex); tabs.set(i, tab); @@ -158,44 +166,41 @@ public class GearModifierScreen extends AbstractElementScreen { updateModifierList(false); } - private TextInputElement createLvlInput() { - ScrollableTextInputElement inputElement = this.addElement( - new ScrollableTextInputElement(Spatials.positionXY(this.getGuiSpatial().width() - 54 - 13, 36).size(26, 12), + private void createTabs() { + for (int i = 0; i < Items.getVaultGearItems().size(); i++) { + addTab(i); + addFakeItemSlot(i); + } + } + + private void addTab(int index) { + TabElement tab = getTabElement(index, index == currIndex); + tabs.add(this.addElement(tab)); + } + + private void addFakeItemSlot(int index) { + ItemStack gearItem = Items.getVaultGearItems().get(index); + this.addElement( + new FakeItemSlotElement<>(getItemPos(index), () -> gearItem, () -> false, + ScreenTextures.EMPTY, ScreenTextures.EMPTY).layout( + this.translateWorldSpatial())); + } + + + // header + + private ScrollableLvlInputElement createLvlInput() { + ScrollableLvlInputElement inputElement = this.addElement( + new ScrollableLvlInputElement(Spatials.positionXY(this.getGuiSpatial().width() - 54 - 13, 36).size(26, 12), Minecraft.getInstance().font) - .layout((screen, gui, parent, world) -> world.translateXY(gui)) + .layout(this.translateWorldSpatial()) ); - inputElement.adjustEditBox(editBox -> { - editBox.setFilter(this::isValidLevel); - editBox.setMaxLength(3); - editBox.setValue(String.valueOf(VaultBarOverlay.vaultLevel)); - }); + inputElement.onTextChanged(s -> updateModifierList(true)); return inputElement; } - - private boolean isValidLevel(String input){ - // reminds me of original vault filters - if (input.isEmpty()) { - return true; - } - int lvl; - try { - lvl = Integer.parseInt(input); - } catch (NumberFormatException numberformatexception) { - return false; - } - if (lvl <= ModConfigs.LEVELS_META.getMaxLevel() && lvl >= 0) { - ScreenLayout.requestLayout(); - return true; - } - if (lvl <= Config.MAX_LEVEL_OVERRIDE.get() && lvl >= 0) { - ScreenLayout.requestLayout(); - return true; - } - return false; - } - - private void createLvlButtons() { + + private void createLvlButtons(ScrollableLvlInputElement lvlInput) { LabelElement minusLabel = new LabelElement<>(Spatials.positionXY(this.getGuiSpatial().width() - 68 - 13, 38), new TextComponent("-"), LabelTextStyle.border4(ChatFormatting.BLACK)) @@ -206,10 +211,10 @@ public class GearModifierScreen extends AbstractElementScreen { .layout(this.translateWorldSpatial()); NineSliceButtonElement btnMinus = new NineSliceButtonElement<>(Spatials.positionXY(this.getGuiSpatial().width() - 72 - 13, 35).size(15, 14), - ScreenTextures.BUTTON_EMPTY_TEXTURES, this::decreaseLvl).layout(this.translateWorldSpatial()); + ScreenTextures.BUTTON_EMPTY_TEXTURES, lvlInput::increment).layout(this.translateWorldSpatial()); NineSliceButtonElement btnPlus = new NineSliceButtonElement<>(Spatials.positionXY(this.getGuiSpatial().width() - 25 - 13, 35).size(15, 14), - ScreenTextures.BUTTON_EMPTY_TEXTURES, this::increaseLvl).layout(this.translateWorldSpatial()); + ScreenTextures.BUTTON_EMPTY_TEXTURES, lvlInput::decrement).layout(this.translateWorldSpatial()); this.addElement(btnMinus); this.addElement(minusLabel); this.addElement(plusLabel); @@ -217,7 +222,7 @@ public class GearModifierScreen extends AbstractElementScreen { } private void toggleLegend() { - this.legendary = !this.legendary; + this.tierIncrease = (tierIncrease + 1) % 3; updateLegendaryLabel(); updateModifierList(true); } @@ -226,7 +231,7 @@ public class GearModifierScreen extends AbstractElementScreen { if (this.legendaryLabel != null) { this.removeElement(this.legendaryLabel); } - var formatting = this.legendary ? ChatFormatting.GOLD : ChatFormatting.WHITE; + var formatting = tierIncrease == 2 ? ChatFormatting.GOLD : tierIncrease == 1 ? ChatFormatting.AQUA : ChatFormatting.WHITE; this.legendaryLabel = new LabelElement<>(Spatials.positionXY(this.getGuiSpatial().width() - 5 - 13, 38), new TextComponent("✦").withStyle(formatting), LabelTextStyle.defaultStyle()) .layout(this.translateWorldSpatial()); @@ -241,38 +246,14 @@ public class GearModifierScreen extends AbstractElementScreen { this.addElement(btnLegend); } - private void createTabs() { - for (int i = 0; i < VHatCanIRoll.getVaultGearItems().size(); i++) { - addTab(i); - addFakeItemSlot(i); - } - } - - private void addTab(int index) { - TabElement tab = getTabElement(index, index == currIndex); - tabs.add(this.addElement(tab)); - } - - private void addFakeItemSlot(int index) { - ItemStack gearItem = VHatCanIRoll.getVaultGearItems().get(index); - this.addElement( - new FakeItemSlotElement<>(getItemPos(index), () -> gearItem, () -> false, - ScreenTextures.EMPTY, ScreenTextures.EMPTY).layout( - this.translateWorldSpatial())); - } - - public boolean isLegendary() { - return legendary; - } - @Override public boolean keyPressed(int keyCode, int scanCode, int modifiers) { // left/right to increase/decrease lvl if (keyCode == InputConstants.KEY_L || keyCode == InputConstants.KEY_RIGHT) { - increaseLvl(); + lvlInput.increment(); } if (keyCode == InputConstants.KEY_H || keyCode == InputConstants.KEY_LEFT) { - decreaseLvl(); + lvlInput.decrement(); } // up/down to scroll up/down if (keyCode == InputConstants.KEY_K || keyCode == InputConstants.KEY_UP) { @@ -283,11 +264,11 @@ public class GearModifierScreen extends AbstractElementScreen { } // tab to next gear item if (keyCode == InputConstants.KEY_TAB && !hasShiftDown()) { - switchTab((currIndex + 1) % VHatCanIRoll.getVaultGearItems().size()); + switchTab((currIndex + 1) % Items.getVaultGearItems().size()); } // shift+tab to previous gear item if (keyCode == InputConstants.KEY_TAB && hasShiftDown()) { - switchTab((currIndex - 1 + VHatCanIRoll.getVaultGearItems().size()) % VHatCanIRoll.getVaultGearItems().size()); + switchTab((currIndex - 1 + Items.getVaultGearItems().size()) % Items.getVaultGearItems().size()); } // alt to toggle legendary if (keyCode == InputConstants.KEY_LALT || keyCode == InputConstants.KEY_RALT) { diff --git a/src/main/java/com/radimous/vhatcaniroll/ui/ModifierListContainer.java b/src/main/java/com/radimous/vhatcaniroll/ui/ModifierListContainer.java new file mode 100644 index 0000000..1bde6e3 --- /dev/null +++ b/src/main/java/com/radimous/vhatcaniroll/ui/ModifierListContainer.java @@ -0,0 +1,77 @@ +package com.radimous.vhatcaniroll.ui; + +import iskallia.vault.client.gui.framework.ScreenTextures; +import iskallia.vault.client.gui.framework.element.LabelElement; +import iskallia.vault.client.gui.framework.element.VerticalScrollClipContainer; +import iskallia.vault.client.gui.framework.spatial.Padding; +import iskallia.vault.client.gui.framework.spatial.Spatials; +import iskallia.vault.client.gui.framework.spatial.spi.ISpatial; +import iskallia.vault.client.gui.framework.text.LabelTextStyle; +import iskallia.vault.config.gear.VaultGearTierConfig; +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.TextComponent; +import net.minecraft.world.item.ItemStack; + +import java.util.Optional; + +import com.radimous.vhatcaniroll.logic.Modifiers; + +public class ModifierListContainer extends VerticalScrollClipContainer { + + public ModifierListContainer(ISpatial spatial, int lvl, int tierIncrease, ItemStack gearPiece) { + super(spatial, Padding.ZERO, ScreenTextures.INSET_BLACK_BACKGROUND); + int labelX = 9; + int labelY = 20; + Optional optCfg = VaultGearTierConfig.getConfig(gearPiece); + + + // Label for the item name and level (GOLD if legendary, AQUA if greater, WHITE if common) + LabelElement itemName = new LabelElement<>( + Spatials.positionXY(labelX, 5).width(this.innerWidth() - labelX).height(15), new TextComponent( + gearPiece.getItem().toString().toUpperCase() + " - LVL " + lvl) + //TODO: make it nicer + .withStyle(ChatFormatting.UNDERLINE).withStyle(tierIncrease == 2 ? ChatFormatting.GOLD : tierIncrease == 1 ? ChatFormatting.AQUA : ChatFormatting.WHITE), LabelTextStyle.defaultStyle() + ); + this.addElement(itemName); + + + if (optCfg.isPresent()) { + VaultGearTierConfig cfg = optCfg.get(); + for (var modifier : Modifiers.getModifierList(lvl, cfg, tierIncrease)) { + LabelElement labelelement = new LabelElement<>( + Spatials.positionXY(labelX, labelY).width(this.innerWidth() - labelX).height(15), modifier, LabelTextStyle.defaultStyle() + ); + /* TODO: maybe weight/chance should be added here, because there is everything you need for custom position + that would require returning something else from getModifierList (maybe List>) + where first component is the modifier and second is the weight/chance or both (depending on the config) + also it should potentionally return a list of modifiers to get all tiers of the modifier + + + I want to display + + and make it expandable to show all tiers of the modifier + + + + + + */ + this.addElement(labelelement); + labelY += 10; + } + } else { + LabelElement labelelement = new LabelElement<>( + Spatials.positionXY(labelX, labelY).width(this.innerWidth() - labelX).height(15), new TextComponent( + "Modifier config for " + gearPiece.getItem() + " not found"), LabelTextStyle.defaultStyle() + ); + this.addElement(labelelement); + } + } + public float getScroll() { + return this.verticalScrollBarElement.getValue(); + } + + public void setScroll(float scroll) { + this.verticalScrollBarElement.setValue(scroll); + } +} \ No newline at end of file diff --git a/src/main/java/com/radimous/vhatcaniroll/ui/ScrollableLvlInputElement.java b/src/main/java/com/radimous/vhatcaniroll/ui/ScrollableLvlInputElement.java new file mode 100644 index 0000000..508f806 --- /dev/null +++ b/src/main/java/com/radimous/vhatcaniroll/ui/ScrollableLvlInputElement.java @@ -0,0 +1,72 @@ +package com.radimous.vhatcaniroll.ui; + +import com.radimous.vhatcaniroll.Config; + +import iskallia.vault.client.gui.framework.element.TextInputElement; +import iskallia.vault.client.gui.framework.screen.layout.ScreenLayout; +import iskallia.vault.client.gui.framework.spatial.spi.ISpatial; +import iskallia.vault.client.gui.overlay.VaultBarOverlay; +import iskallia.vault.init.ModConfigs; +import net.minecraft.client.gui.Font; + +public class ScrollableLvlInputElement extends TextInputElement { + public ScrollableLvlInputElement(ISpatial spatial, Font font) { + super(spatial, font); + } + + @Override + public boolean onMouseScrolled(double mouseX, double mouseY, double delta) { + if (this.isMouseOver(mouseX, mouseY)) { + int val = parseInt(this.getInput()); + val += delta > 0 ? 1 : -1; + this.setInput(String.valueOf(val)); + return true; + } + this.adjustEditBox(editBox -> { + editBox.setFilter(s -> isValidLevel(parseInt(s))); + editBox.setMaxLength(3); + editBox.setValue(String.valueOf(VaultBarOverlay.vaultLevel)); + }); + return super.onMouseScrolled(mouseX, mouseY, delta); + } + + + public int getValue() { + return parseInt(this.getInput()); + } + + public void setValue(int value) { + if (isValidLevel(value)) { + this.setInput(String.valueOf(value)); + } + } + + public void increment() { + this.setValue(getValue() + 1); + } + + public void decrement() { + this.setValue(getValue() - 1); + } + + private int parseInt(String val) { + try { + return Integer.parseInt(val); + } catch (NumberFormatException e) { + return 0; + } + } + + public boolean isValidLevel(int lvl){ + if (lvl <= ModConfigs.LEVELS_META.getMaxLevel() && lvl >= 0) { + ScreenLayout.requestLayout(); + return true; + } + if (lvl <= Config.MAX_LEVEL_OVERRIDE.get() && lvl >= 0) { + ScreenLayout.requestLayout(); + return true; + } + return false; + } + +}