Compare commits
32 commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1d847e6880 | |||
| 38d94c663b | |||
| 5c161a0f7c | |||
| 6b50b6cb3b | |||
| 3325839d7d | |||
| 5e02499406 | |||
| 10f586e5db | |||
| a355c7982a | |||
| 97d87a1d36 | |||
| f011e8509b | |||
| 2e10d4afce | |||
| 3e70c30b89 | |||
| 93fa1a89f2 | |||
| 1e89a8f3e7 | |||
| ab5fbdfec2 | |||
| 15ebedce84 | |||
| 19380da36f | |||
| 5bfc6c83ba | |||
| e758d2b787 | |||
| ef0bfec587 | |||
| 64b42515df | |||
| 606a54e3af | |||
| bf09fb18d0 | |||
| b90d503174 | |||
| 78c1ab279d | |||
| d2969663bc | |||
| 1ef461ab37 | |||
| 602d181e58 | |||
| addd286756 | |||
| 7a04012234 | |||
| 87f94725dd | |||
| 9f7c3df47e |
30 changed files with 2195 additions and 697 deletions
70
.github/workflows/gradle.yml
vendored
Normal file
70
.github/workflows/gradle.yml
vendored
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
# This workflow uses actions that are not certified by GitHub.
|
||||||
|
# They are provided by a third-party and are governed by
|
||||||
|
# separate terms of service, privacy policy, and support
|
||||||
|
# documentation.
|
||||||
|
# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time
|
||||||
|
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle
|
||||||
|
|
||||||
|
name: Java CI with Gradle
|
||||||
|
|
||||||
|
on:
|
||||||
|
push
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Set up JDK 17
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
java-version: '17'
|
||||||
|
distribution: 'temurin'
|
||||||
|
|
||||||
|
# Configure Gradle for optimal use in GitHub Actions, including caching of downloaded dependencies.
|
||||||
|
# See: https://github.com/gradle/actions/blob/main/setup-gradle/README.md
|
||||||
|
- name: Setup Gradle
|
||||||
|
uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0
|
||||||
|
|
||||||
|
- name: Build with Gradle Wrapper
|
||||||
|
run: ./gradlew build
|
||||||
|
|
||||||
|
# NOTE: The Gradle Wrapper is the default and recommended way to run Gradle (https://docs.gradle.org/current/userguide/gradle_wrapper.html).
|
||||||
|
# If your project does not have the Gradle Wrapper configured, you can use the following configuration to run Gradle with a specified version.
|
||||||
|
#
|
||||||
|
# - name: Setup Gradle
|
||||||
|
# uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0
|
||||||
|
# with:
|
||||||
|
# gradle-version: '8.9'
|
||||||
|
#
|
||||||
|
# - name: Build with Gradle 8.9
|
||||||
|
# run: gradle build
|
||||||
|
- name: Upload artifacts
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: artifacts
|
||||||
|
path: build/libs/*.jar
|
||||||
|
|
||||||
|
dependency-submission:
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Set up JDK 17
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
java-version: '17'
|
||||||
|
distribution: 'temurin'
|
||||||
|
|
||||||
|
# Generates and submits a dependency graph, enabling Dependabot Alerts for all project dependencies.
|
||||||
|
# See: https://github.com/gradle/actions/blob/main/dependency-submission/README.md
|
||||||
|
- name: Generate and submit dependency graph
|
||||||
|
uses: gradle/actions/dependency-submission@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0
|
||||||
|
|
||||||
23
README.md
Normal file
23
README.md
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
# VHatCanIRoll
|
||||||
|
Shows you all possible modifiers you can roll/craft on vault gear at any level.
|
||||||
|
In-game version of the [gear page](https://vault-hunters.netlify.app/gear), you don't have to leave the game now to see what you can modifiers you can get.
|
||||||
|
Triangles with the same color indicate modifier exclusivity (you can't roll 2 modifiers with the same color).
|
||||||
|
|
||||||
|
You can open the screen by pressing the "Gear Modifiers" button in the Vault Screen (right below the quest button) or by pressing dedicated keybind (unbound by default).
|
||||||
|
You can disable or move the button in the config.
|
||||||
|
|
||||||
|
Supports [Wold's vaults](https://www.curseforge.com/minecraft/modpacks/wolds-vaults)
|
||||||
|
|
||||||
|
Client side only
|
||||||
|
|
||||||
|
Keyboard navigation:
|
||||||
|
| KEY | ACTION |
|
||||||
|
| --- | --- |
|
||||||
|
| left arrow (h) | decrease lvl |
|
||||||
|
| right arrow (l) | increase lvl |
|
||||||
|
| up arrow (k) | scroll up |
|
||||||
|
| down arrow (j) | scroll down |
|
||||||
|
| tab | move to next gear piece |
|
||||||
|
| shift + tab | move to previous gear piece |
|
||||||
|
| alt | toggle legendary modifiers |
|
||||||
|
| ctrl + , | toggle compact "+lvl to abilities" modifier view |
|
||||||
|
|
@ -173,8 +173,8 @@ dependencies {
|
||||||
annotationProcessor 'org.spongepowered:mixin:0.8.5:processor'
|
annotationProcessor 'org.spongepowered:mixin:0.8.5:processor'
|
||||||
|
|
||||||
//VH
|
//VH
|
||||||
implementation fg.deobf("curse.maven:vault-hunters-official-mod-458203:5631250")
|
implementation fg.deobf("curse.maven:vault-hunters-official-mod-458203:5925633")
|
||||||
// implementation fg.deobf("curse.maven:wolds-vaults-official-mod-958799:5622985")
|
|
||||||
//deps
|
//deps
|
||||||
implementation fg.deobf("curse.maven:curios-309927:4418032")
|
implementation fg.deobf("curse.maven:curios-309927:4418032")
|
||||||
implementation fg.deobf("curse.maven:sophisticated-backpacks-vault-hunters-edition-696425:4287544")
|
implementation fg.deobf("curse.maven:sophisticated-backpacks-vault-hunters-edition-696425:4287544")
|
||||||
|
|
@ -188,6 +188,8 @@ dependencies {
|
||||||
implementation fg.deobf("curse.maven:alexs-mobs-426558:3853078") // wold plushie effects
|
implementation fg.deobf("curse.maven:alexs-mobs-426558:3853078") // wold plushie effects
|
||||||
implementation fg.deobf("curse.maven:citadel-331936:3783096") // alex mobs dep
|
implementation fg.deobf("curse.maven:citadel-331936:3783096") // alex mobs dep
|
||||||
|
|
||||||
|
implementation fg.deobf("curse.maven:create-328085:4550986") // config
|
||||||
|
|
||||||
//faster loading
|
//faster loading
|
||||||
implementation fg.deobf("curse.maven:lazydfu-433518:3209972")
|
implementation fg.deobf("curse.maven:lazydfu-433518:3209972")
|
||||||
implementation fg.deobf("curse.maven:modernfix-790626:4565795")
|
implementation fg.deobf("curse.maven:modernfix-790626:4565795")
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ mod_name=VHat Can I Roll?
|
||||||
# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
|
# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
|
||||||
mod_license=GNU LGPL 3.0
|
mod_license=GNU LGPL 3.0
|
||||||
# The mod version. See https://semver.org/
|
# The mod version. See https://semver.org/
|
||||||
mod_version=1.1
|
mod_version=1.5
|
||||||
# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository.
|
# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository.
|
||||||
# This should match the base package used for the mod sources.
|
# This should match the base package used for the mod sources.
|
||||||
# See https://maven.apache.org/guides/mini/guide-naming-conventions.html
|
# See https://maven.apache.org/guides/mini/guide-naming-conventions.html
|
||||||
|
|
|
||||||
0
gradlew
vendored
Normal file → Executable file
0
gradlew
vendored
Normal file → Executable file
|
|
@ -1,23 +1,30 @@
|
||||||
package com.radimous.vhatcaniroll;
|
package com.radimous.vhatcaniroll;
|
||||||
|
|
||||||
|
import iskallia.vault.config.gear.VaultGearTierConfig;
|
||||||
import net.minecraftforge.common.ForgeConfigSpec;
|
import net.minecraftforge.common.ForgeConfigSpec;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class Config {
|
public class Config {
|
||||||
public static final ForgeConfigSpec SPEC;
|
public static final ForgeConfigSpec SPEC;
|
||||||
public static final ForgeConfigSpec.BooleanValue VAULT_SCREEN_BUTTON;
|
public static final ForgeConfigSpec.BooleanValue VAULT_SCREEN_BUTTON;
|
||||||
public static final ForgeConfigSpec.BooleanValue ALLOW_DUPE;
|
|
||||||
public static final ForgeConfigSpec.IntValue BUTTON_X;
|
public static final ForgeConfigSpec.IntValue BUTTON_X;
|
||||||
public static final ForgeConfigSpec.IntValue BUTTON_Y;
|
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.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;
|
||||||
|
public static final ForgeConfigSpec.BooleanValue QOL_HUNTERS_CONFLICT_RESOLUTION;
|
||||||
|
public static final ForgeConfigSpec.BooleanValue SHOW_UNOBTAINABLE_CRAFTED;
|
||||||
|
public static final ForgeConfigSpec.BooleanValue DEBUG_UNIQUE_GEAR;
|
||||||
|
// string instead of enum, because forge would remove enum values that are not present in the enum
|
||||||
|
// (this could cause problems if mods are extending the enum - like wold's)
|
||||||
|
public static final ForgeConfigSpec.ConfigValue<List<String>> AFFIX_TAG_GROUP_CHANCE_BLACKLIST;
|
||||||
|
|
||||||
|
|
||||||
static {
|
static {
|
||||||
ForgeConfigSpec.Builder builder = new ForgeConfigSpec.Builder();
|
ForgeConfigSpec.Builder builder = new ForgeConfigSpec.Builder();
|
||||||
|
|
||||||
COMBINE_LVL_TO_ABILITIES = builder
|
|
||||||
.comment("combine +lvl to abilities into one row")
|
|
||||||
.define("combineAddedLvlToAbilities", false);
|
|
||||||
|
|
||||||
builder.push("BUTTON");
|
builder.push("BUTTON");
|
||||||
VAULT_SCREEN_BUTTON = builder
|
VAULT_SCREEN_BUTTON = builder
|
||||||
.comment("open VHat can I roll? from vault screen")
|
.comment("open VHat can I roll? from vault screen")
|
||||||
|
|
@ -25,20 +32,42 @@ public class Config {
|
||||||
BUTTON_X = builder
|
BUTTON_X = builder
|
||||||
.comment("x position of the button")
|
.comment("x position of the button")
|
||||||
.defineInRange("buttonPositionX", 5, Integer.MIN_VALUE, Integer.MAX_VALUE);
|
.defineInRange("buttonPositionX", 5, Integer.MIN_VALUE, Integer.MAX_VALUE);
|
||||||
|
|
||||||
BUTTON_Y = builder
|
BUTTON_Y = builder
|
||||||
.comment("y position of the button")
|
.comment("y position of the button (109 default, 130 for QOL Hunters)")
|
||||||
.defineInRange("buttonPositionY", 109, Integer.MIN_VALUE, Integer.MAX_VALUE);
|
.defineInRange("buttonPositionY", 109, Integer.MIN_VALUE, Integer.MAX_VALUE);
|
||||||
builder.pop();
|
builder.pop();
|
||||||
|
|
||||||
builder.push("DEBUG");
|
builder.push("DEBUG");
|
||||||
ALLOW_DUPE = builder
|
QOL_HUNTERS_CONFLICT_RESOLUTION = builder
|
||||||
.comment("allow duplicate modifiers")
|
.comment("QOL Hunters conflict resolution (shouldn't be disabled unless it causes issues)")
|
||||||
.define("allowDupe", false);
|
.define("QOLHuntersConflictResolution", true);
|
||||||
|
AFFIX_TAG_GROUP_CHANCE_BLACKLIST = builder
|
||||||
|
.comment("vhcir won't show chance/weight for affixes in these groups")
|
||||||
|
.define("affixTagGroupBlacklist", List.of(VaultGearTierConfig.ModifierAffixTagGroup.CRAFTED_PREFIX.name(), VaultGearTierConfig.ModifierAffixTagGroup.CRAFTED_SUFFIX.name()));
|
||||||
MAX_LEVEL_OVERRIDE = builder
|
MAX_LEVEL_OVERRIDE = builder
|
||||||
.comment("override max level")
|
.comment("override max level")
|
||||||
.defineInRange("maxLevelOverride", -1, -1, Integer.MAX_VALUE);
|
.defineInRange("maxLevelOverride", -1, -1, Integer.MAX_VALUE);
|
||||||
|
DEBUG_UNIQUE_GEAR = builder
|
||||||
|
.comment("debug unique gear")
|
||||||
|
.define("debugUniqueGear", false);
|
||||||
builder.pop();
|
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);
|
||||||
|
|
||||||
|
SHOW_UNOBTAINABLE_CRAFTED = builder
|
||||||
|
.comment("show unobtainable crafted modifiers (above current lvl)")
|
||||||
|
.define("showUnobtainableCrafted", false);
|
||||||
SPEC = builder.build();
|
SPEC = builder.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,303 +0,0 @@
|
||||||
package com.radimous.vhatcaniroll;
|
|
||||||
|
|
||||||
import com.mojang.blaze3d.platform.InputConstants;
|
|
||||||
import iskallia.vault.client.gui.framework.ScreenRenderers;
|
|
||||||
import iskallia.vault.client.gui.framework.ScreenTextures;
|
|
||||||
import iskallia.vault.client.gui.framework.element.FakeItemSlotElement;
|
|
||||||
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;
|
|
||||||
import iskallia.vault.client.gui.framework.screen.AbstractElementScreen;
|
|
||||||
import iskallia.vault.client.gui.framework.screen.layout.ScreenLayout;
|
|
||||||
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;
|
|
||||||
import net.minecraft.network.chat.TranslatableComponent;
|
|
||||||
import net.minecraft.world.item.ItemStack;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class GearModifierScreen extends AbstractElementScreen {
|
|
||||||
//TODO: code cleanup - variable naming, magic numbers, some logic reordering etc
|
|
||||||
|
|
||||||
private ModifierListContainer modifierList;
|
|
||||||
private final TextInputElement<?> lvlInput;
|
|
||||||
private boolean legendary;
|
|
||||||
private LabelElement<?> legendaryLabel;
|
|
||||||
|
|
||||||
private int currIndex = 0;
|
|
||||||
private final List<TabElement<?>> tabs = new ArrayList<>();
|
|
||||||
|
|
||||||
public GearModifierScreen() {
|
|
||||||
super(new TranslatableComponent("vhatcaniroll.screen.title"), ScreenRenderers.getBuffered(), ScreenTooltipRenderer::create);
|
|
||||||
|
|
||||||
// make screen size 95% of the window height and width that looks good
|
|
||||||
this.setGuiSize(Spatials.size(340, 300).height((int) (
|
|
||||||
(Minecraft.getInstance().getWindow().getHeight() / Minecraft.getInstance().getWindow().getGuiScale()) *
|
|
||||||
0.95)));
|
|
||||||
|
|
||||||
// outer background
|
|
||||||
NineSliceElement<?> background = new NineSliceElement<>(
|
|
||||||
Spatials.positionXY(0, 30).size(this.getGuiSpatial().width(), this.getGuiSpatial().height() - 30),
|
|
||||||
ScreenTextures.DEFAULT_WINDOW_BACKGROUND
|
|
||||||
).layout(this.translateWorldSpatial());
|
|
||||||
|
|
||||||
// window title
|
|
||||||
LabelElement<?> windowName = new LabelElement<>(
|
|
||||||
Spatials.positionXY(7, 38).size(this.getGuiSpatial().width() / 2 - 7, 20),
|
|
||||||
this.title.copy().withStyle(ChatFormatting.BLACK),
|
|
||||||
LabelTextStyle.defaultStyle()
|
|
||||||
).layout(this.translateWorldSpatial());
|
|
||||||
|
|
||||||
|
|
||||||
this.addElement(background);
|
|
||||||
this.addElement(windowName);
|
|
||||||
|
|
||||||
createTabs();
|
|
||||||
|
|
||||||
this.lvlInput = this.addElement(createLvlInput());
|
|
||||||
createLvlButtons();
|
|
||||||
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());
|
|
||||||
this.addElement(this.modifierList);
|
|
||||||
}
|
|
||||||
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
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());
|
|
||||||
if (keepScroll) {
|
|
||||||
this.modifierList.setScroll(oldScroll);
|
|
||||||
}
|
|
||||||
this.addElement(this.modifierList);
|
|
||||||
ScreenLayout.requestLayout();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private ILayoutStrategy translateWorldSpatial() {
|
|
||||||
return (screen, gui, parent, world) -> world.translateXY(this.getGuiSpatial());
|
|
||||||
}
|
|
||||||
|
|
||||||
private IPosition getPos(int tabIndex, boolean selected) {
|
|
||||||
if (tabIndex < 11){
|
|
||||||
return Spatials.positionXY(5 + tabIndex * 30, 2 + (selected ? 0 : 4));
|
|
||||||
}
|
|
||||||
return Spatials.positionXY(337 + (selected? 0:3), 35 + (tabIndex-11) * 30);
|
|
||||||
}
|
|
||||||
private ISpatial getItemPos(int tabIndex) {
|
|
||||||
if (tabIndex < 11){
|
|
||||||
return Spatials.positionXY(10 + tabIndex * 30, 11);
|
|
||||||
}
|
|
||||||
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),
|
|
||||||
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),
|
|
||||||
new TextureAtlasElement<>(
|
|
||||||
selected ? ScreenTextures.TAB_BACKGROUND_RIGHT_SELECTED : ScreenTextures.TAB_BACKGROUND_RIGHT),
|
|
||||||
new TextureAtlasElement<>(ScreenTextures.EMPTY), () -> switchTab(tabIndex))
|
|
||||||
.layout(this.translateWorldSpatial());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void switchTab(int tabIndex) {
|
|
||||||
for (int i = 0; i < VHatCanIRoll.getVaultGearItems().size(); i++) {
|
|
||||||
this.removeElement(tabs.get(i));
|
|
||||||
TabElement<?> tab = getTabElement(i, i == tabIndex);
|
|
||||||
tabs.set(i, tab);
|
|
||||||
this.addElement(tab);
|
|
||||||
}
|
|
||||||
this.currIndex = tabIndex;
|
|
||||||
updateModifierList(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private TextInputElement<?> createLvlInput() {
|
|
||||||
ScrollableTextInputElement inputElement = this.addElement(
|
|
||||||
new ScrollableTextInputElement(Spatials.positionXY(this.getGuiSpatial().width() - 54 - 13, 36).size(26, 12),
|
|
||||||
Minecraft.getInstance().font)
|
|
||||||
.layout((screen, gui, parent, world) -> world.translateXY(gui))
|
|
||||||
);
|
|
||||||
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() {
|
|
||||||
LabelElement<?> minusLabel =
|
|
||||||
new LabelElement<>(Spatials.positionXY(this.getGuiSpatial().width() - 68 - 13, 38), new TextComponent("-"),
|
|
||||||
LabelTextStyle.border4(ChatFormatting.BLACK))
|
|
||||||
.layout(this.translateWorldSpatial());
|
|
||||||
LabelElement<?> plusLabel =
|
|
||||||
new LabelElement<>(Spatials.positionXY(this.getGuiSpatial().width() - 21 - 13, 38), new TextComponent("+"),
|
|
||||||
LabelTextStyle.border4(ChatFormatting.BLACK))
|
|
||||||
.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());
|
|
||||||
NineSliceButtonElement<?> btnPlus =
|
|
||||||
new NineSliceButtonElement<>(Spatials.positionXY(this.getGuiSpatial().width() - 25 - 13, 35).size(15, 14),
|
|
||||||
ScreenTextures.BUTTON_EMPTY_TEXTURES, this::increaseLvl).layout(this.translateWorldSpatial());
|
|
||||||
this.addElement(btnMinus);
|
|
||||||
this.addElement(minusLabel);
|
|
||||||
this.addElement(plusLabel);
|
|
||||||
this.addElement(btnPlus);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void toggleLegend() {
|
|
||||||
this.legendary = !this.legendary;
|
|
||||||
updateLegendaryLabel();
|
|
||||||
updateModifierList(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateLegendaryLabel() {
|
|
||||||
if (this.legendaryLabel != null) {
|
|
||||||
this.removeElement(this.legendaryLabel);
|
|
||||||
}
|
|
||||||
var formatting = this.legendary ? ChatFormatting.GOLD : ChatFormatting.WHITE;
|
|
||||||
this.legendaryLabel = new LabelElement<>(Spatials.positionXY(this.getGuiSpatial().width() - 5 - 13, 38),
|
|
||||||
new TextComponent("✦").withStyle(formatting), LabelTextStyle.defaultStyle())
|
|
||||||
.layout(this.translateWorldSpatial());
|
|
||||||
this.addElement(legendaryLabel);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createLegendaryButton() {
|
|
||||||
updateLegendaryLabel();
|
|
||||||
NineSliceButtonElement<?> btnLegend =
|
|
||||||
new NineSliceButtonElement<>(Spatials.positionXY(this.getGuiSpatial().width() - 8 - 13, 35).size(14, 14),
|
|
||||||
ScreenTextures.BUTTON_EMPTY_TEXTURES, this::toggleLegend).layout(this.translateWorldSpatial());
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
if (keyCode == InputConstants.KEY_H || keyCode == InputConstants.KEY_LEFT) {
|
|
||||||
decreaseLvl();
|
|
||||||
}
|
|
||||||
// up/down to scroll up/down
|
|
||||||
if (keyCode == InputConstants.KEY_K || keyCode == InputConstants.KEY_UP) {
|
|
||||||
this.modifierList.onMouseScrolled(0, 0, 1);
|
|
||||||
}
|
|
||||||
if (keyCode == InputConstants.KEY_J || keyCode == InputConstants.KEY_DOWN) {
|
|
||||||
this.modifierList.onMouseScrolled(0, 0, -1);
|
|
||||||
}
|
|
||||||
// tab to next gear item
|
|
||||||
if (keyCode == InputConstants.KEY_TAB && !hasShiftDown()) {
|
|
||||||
switchTab((currIndex + 1) % VHatCanIRoll.getVaultGearItems().size());
|
|
||||||
}
|
|
||||||
// shift+tab to previous gear item
|
|
||||||
if (keyCode == InputConstants.KEY_TAB && hasShiftDown()) {
|
|
||||||
switchTab((currIndex - 1 + VHatCanIRoll.getVaultGearItems().size()) % VHatCanIRoll.getVaultGearItems().size());
|
|
||||||
}
|
|
||||||
// alt to toggle legendary
|
|
||||||
if (keyCode == InputConstants.KEY_LALT || keyCode == InputConstants.KEY_RALT) {
|
|
||||||
toggleLegend();
|
|
||||||
}
|
|
||||||
// ctrl + , to toggle compact +lvl to abilities
|
|
||||||
if (keyCode == InputConstants.KEY_COMMA && hasControlDown()) {
|
|
||||||
Config.COMBINE_LVL_TO_ABILITIES.set(!Config.COMBINE_LVL_TO_ABILITIES.get());
|
|
||||||
updateModifierList(true);
|
|
||||||
}
|
|
||||||
return super.keyPressed(keyCode, scanCode, modifiers);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,233 +0,0 @@
|
||||||
package com.radimous.vhatcaniroll;
|
|
||||||
|
|
||||||
import com.radimous.vhatcaniroll.mixin.EffectConfigAccessor;
|
|
||||||
import com.radimous.vhatcaniroll.mixin.VaultGearTierConfigAccessor;
|
|
||||||
import iskallia.vault.config.gear.VaultGearTierConfig;
|
|
||||||
import iskallia.vault.gear.attribute.VaultGearAttribute;
|
|
||||||
import iskallia.vault.gear.attribute.VaultGearAttributeRegistry;
|
|
||||||
import iskallia.vault.gear.attribute.ability.AbilityLevelAttribute;
|
|
||||||
import iskallia.vault.gear.attribute.ability.special.base.SpecialAbilityModification;
|
|
||||||
import iskallia.vault.gear.attribute.config.BooleanFlagGenerator;
|
|
||||||
import iskallia.vault.gear.attribute.config.ConfigurableAttributeGenerator;
|
|
||||||
import iskallia.vault.gear.attribute.custom.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;
|
|
||||||
import net.minecraft.network.chat.TextComponent;
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
|
||||||
import net.minecraftforge.fml.LogicalSide;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
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 {
|
|
||||||
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<Component> getModifierList(int lvl, VaultGearTierConfig cfg, boolean legendary) {
|
|
||||||
Map<VaultGearTierConfig.ModifierAffixTagGroup, VaultGearTierConfig.AttributeGroup> modifierGroup =
|
|
||||||
((VaultGearTierConfigAccessor) cfg).getModifierGroup();
|
|
||||||
ArrayList<Component> modList = new ArrayList<>();
|
|
||||||
for (VaultGearTierConfig.ModifierAffixTagGroup affixTagGroup : modifierGroup.keySet()) {
|
|
||||||
processAffixTagGroup(lvl, affixTagGroup, modifierGroup, modList, legendary);
|
|
||||||
}
|
|
||||||
return modList;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void processAffixTagGroup(int lvl, VaultGearTierConfig.ModifierAffixTagGroup affixTagGroup,
|
|
||||||
Map<VaultGearTierConfig.ModifierAffixTagGroup, VaultGearTierConfig.AttributeGroup> modifierGroup,
|
|
||||||
ArrayList<Component> modList, boolean legendary) {
|
|
||||||
if (affixTagGroup.equals(VaultGearTierConfig.ModifierAffixTagGroup.ABILITY_ENHANCEMENT)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (modifierGroup.get(affixTagGroup).isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
modList.add(new TextComponent(affixTagGroup.toString().replace("_", " ")).withStyle(ChatFormatting.BOLD));
|
|
||||||
|
|
||||||
Map<String, Integer> groupCounts = countGroups(lvl, affixTagGroup, modifierGroup, legendary);
|
|
||||||
|
|
||||||
List<String> grList = new ArrayList<>();
|
|
||||||
for (VaultGearTierConfig.ModifierTierGroup modifierTierGroup : modifierGroup.get(affixTagGroup)) {
|
|
||||||
ArrayList<VaultGearTierConfig.ModifierTier<?>> mTierList;
|
|
||||||
if (legendary) {
|
|
||||||
mTierList = getLegendaryModifierTiers(lvl, modifierTierGroup);
|
|
||||||
} else {
|
|
||||||
mTierList = getModifierTiers(lvl, modifierTierGroup);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mTierList.isEmpty()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
String modGr = modifierTierGroup.getModifierGroup();
|
|
||||||
Component newMod = getVal(
|
|
||||||
Objects.requireNonNull(VaultGearAttributeRegistry.getAttribute(modifierTierGroup.getAttribute())),
|
|
||||||
mTierList);
|
|
||||||
if (groupCounts.get(modGr) > 1 && !grList.contains(modGr)) {
|
|
||||||
grList.add(modGr);
|
|
||||||
}
|
|
||||||
int index = grList.indexOf(modGr); // index used to determine color
|
|
||||||
MutableComponent full;
|
|
||||||
if (index == -1) {
|
|
||||||
full = new TextComponent(" ");
|
|
||||||
} else {
|
|
||||||
full = new TextComponent("► ").withStyle(COLORS[index % COLORS.length]);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
modList.add(TextComponent.EMPTY);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Map<String, Integer> countGroups(int lvl, VaultGearTierConfig.ModifierAffixTagGroup affixTagGroup,
|
|
||||||
Map<VaultGearTierConfig.ModifierAffixTagGroup, VaultGearTierConfig.AttributeGroup> modifierGroup,
|
|
||||||
boolean legendary) {
|
|
||||||
Map<String, Integer> groupCounts = new HashMap<>();
|
|
||||||
for (VaultGearTierConfig.ModifierTierGroup modifierTierGroup : modifierGroup.get(affixTagGroup)) {
|
|
||||||
ArrayList<VaultGearTierConfig.ModifierTier<?>> mTierList;
|
|
||||||
if (legendary) {
|
|
||||||
mTierList = getLegendaryModifierTiers(lvl, modifierTierGroup);
|
|
||||||
} else {
|
|
||||||
mTierList = getModifierTiers(lvl, modifierTierGroup);
|
|
||||||
}
|
|
||||||
if (mTierList.isEmpty()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
groupCounts.put(modifierTierGroup.getModifierGroup(),
|
|
||||||
groupCounts.getOrDefault(modifierTierGroup.getModifierGroup(), 0) + 1);
|
|
||||||
}
|
|
||||||
return groupCounts;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ArrayList<VaultGearTierConfig.ModifierTier<?>> getLegendaryModifierTiers(int lvl,
|
|
||||||
VaultGearTierConfig.ModifierTierGroup modifierTierGroup) {
|
|
||||||
|
|
||||||
var res = new ArrayList<VaultGearTierConfig.ModifierTier<?>>();
|
|
||||||
var highest = modifierTierGroup.getHighestForLevel(lvl);
|
|
||||||
if (highest == null) {
|
|
||||||
return res; // empty
|
|
||||||
}
|
|
||||||
int index = Math.min(highest.getModifierTier() + 2, modifierTierGroup.size() - 1);
|
|
||||||
var legendTier = modifierTierGroup.get(index);
|
|
||||||
if (legendTier == null || legendTier.getWeight() == 0){
|
|
||||||
return res; // empty
|
|
||||||
}
|
|
||||||
if (legendTier.getModifierConfiguration() instanceof BooleanFlagGenerator.BooleanFlag bf &&
|
|
||||||
!bf.get()) {
|
|
||||||
return res; // empty
|
|
||||||
}
|
|
||||||
res.add(legendTier);
|
|
||||||
return res; // only one
|
|
||||||
}
|
|
||||||
@NotNull private static ArrayList<VaultGearTierConfig.ModifierTier<?>> getModifierTiers(int lvl,
|
|
||||||
VaultGearTierConfig.ModifierTierGroup modifierTierGroup) {
|
|
||||||
return modifierTierGroup.getModifiersForLevel(lvl).stream()
|
|
||||||
.filter(x -> x.getWeight() != 0
|
|
||||||
&& !(x.getModifierConfiguration() instanceof BooleanFlagGenerator.BooleanFlag bf &&
|
|
||||||
!bf.get())) // bool with false :( looking at you, soulbound
|
|
||||||
.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<ModifierTier<?>>
|
|
||||||
private static <T, C> Component getVal(VaultGearAttribute<T> atr,
|
|
||||||
ArrayList<VaultGearTierConfig.ModifierTier<?>> val) {
|
|
||||||
if (val.isEmpty()) {
|
|
||||||
return new TextComponent("ERR - EMPTY VAL");
|
|
||||||
}
|
|
||||||
ConfigurableAttributeGenerator<T, C> atrGenerator = (ConfigurableAttributeGenerator<T, C>) atr.getGenerator();
|
|
||||||
if (atrGenerator == null) {
|
|
||||||
return new TextComponent("ERR - NULL GENERATOR");
|
|
||||||
}
|
|
||||||
C minConfig = (C) val.get(0).getModifierConfiguration();
|
|
||||||
C maxConfig = (C) val.get(val.size() - 1).getModifierConfiguration();
|
|
||||||
MutableComponent res;
|
|
||||||
ResourceLocation atrRegName = atr.getRegistryName();
|
|
||||||
if (atrRegName == null) {
|
|
||||||
return new TextComponent("ERR - NULL REGISTRY NAME");
|
|
||||||
}
|
|
||||||
String atrName = atrRegName.toString();
|
|
||||||
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
if (atrName.equals("the_vault:effect_avoidance") && minConfigDisplay != null) {
|
|
||||||
// res -> "30% - 50%"
|
|
||||||
// single -> "30% Poison Avoidance"
|
|
||||||
// minRange -> "30%"
|
|
||||||
var single = minConfigDisplay.withStyle(atr.getReader().getColoredTextStyle());
|
|
||||||
var minRange = atrGenerator.getConfigRangeDisplay(atr.getReader(), minConfig, minConfig);
|
|
||||||
if (minRange != null && res != null) {
|
|
||||||
res.append(single.getString().replace(minRange.getString(), ""));
|
|
||||||
// res -> "30% - 50% Poison Avoidance"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (minConfig instanceof EffectGearAttribute.Config minEffectConfig
|
|
||||||
&& maxConfig instanceof EffectGearAttribute.Config
|
|
||||||
&& maxConfigDisplay != null) {
|
|
||||||
var effectStr = ((EffectConfigAccessor)minEffectConfig).getAmplifier() + "-" +
|
|
||||||
maxConfigDisplay.getString();
|
|
||||||
return new TextComponent(effectStr).withStyle(atr.getReader().getColoredTextStyle());
|
|
||||||
|
|
||||||
}
|
|
||||||
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,
|
|
||||||
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(SpecialAbilityModification.getAbilityStyle()));
|
|
||||||
return abComp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
package com.radimous.vhatcaniroll;
|
package com.radimous.vhatcaniroll;
|
||||||
|
|
||||||
import com.mojang.blaze3d.platform.InputConstants;
|
import com.mojang.blaze3d.platform.InputConstants;
|
||||||
|
import com.radimous.vhatcaniroll.ui.GearModifierScreen;
|
||||||
|
|
||||||
import net.minecraft.client.KeyMapping;
|
import net.minecraft.client.KeyMapping;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
|
|
||||||
|
|
@ -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<ModifierListContainer> {
|
|
||||||
|
|
||||||
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<VaultGearTierConfig> 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
package com.radimous.vhatcaniroll;
|
||||||
|
|
||||||
|
import net.minecraftforge.common.ForgeConfigSpec;
|
||||||
|
|
||||||
|
public class QOLHuntersCompat {
|
||||||
|
|
||||||
|
private static boolean qolHuntersLoaded = true;
|
||||||
|
private static ForgeConfigSpec.BooleanValue qolConfigButton = null;
|
||||||
|
|
||||||
|
public static void resolveQOLHuntersButtonConflict(){
|
||||||
|
if(!Config.QOL_HUNTERS_CONFLICT_RESOLUTION.get()){
|
||||||
|
// just for debugging or if it blows up
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!qolHuntersLoaded) {
|
||||||
|
if (Config.BUTTON_Y.get() == 130) {
|
||||||
|
Config.BUTTON_Y.set(109);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (qolConfigButton == null) {
|
||||||
|
// use reflection to avoid a million dependencies
|
||||||
|
try {
|
||||||
|
Class<?> cl = Class.forName("io.iridium.qolhunters.config.QOLHuntersClientConfigs");
|
||||||
|
Object qolButton = cl.getField("SHOW_CONFIG_BUTTON").get(null);
|
||||||
|
qolConfigButton = (ForgeConfigSpec.BooleanValue) qolButton;
|
||||||
|
} catch (NoSuchFieldException | ClassNotFoundException | IllegalAccessException e) {
|
||||||
|
qolHuntersLoaded = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if qol button, move our button down
|
||||||
|
if (qolConfigButton != null && qolConfigButton.get() && Config.BUTTON_Y.get() == 109) {
|
||||||
|
Config.BUTTON_Y.set(130);
|
||||||
|
}
|
||||||
|
// if no qol button, move our button up
|
||||||
|
if ((qolConfigButton == null || !qolConfigButton.get()) && Config.BUTTON_Y.get() == 130) {
|
||||||
|
Config.BUTTON_Y.set(109);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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<ScrollableTextInputElement> {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,73 +1,16 @@
|
||||||
package com.radimous.vhatcaniroll;
|
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.common.MinecraftForge;
|
||||||
import net.minecraftforge.fml.ModLoadingContext;
|
import net.minecraftforge.fml.ModLoadingContext;
|
||||||
import net.minecraftforge.fml.common.Mod;
|
import net.minecraftforge.fml.common.Mod;
|
||||||
import net.minecraftforge.fml.config.ModConfig;
|
import net.minecraftforge.fml.config.ModConfig;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Mod("vhatcaniroll")
|
@Mod("vhatcaniroll")
|
||||||
public class VHatCanIRoll {
|
public class VHatCanIRoll {
|
||||||
|
|
||||||
public static final String MODID = "vhatcaniroll";
|
public static final String MODID = "vhatcaniroll";
|
||||||
private static final List<ItemStack> GEAR_ITEMS = new ArrayList<>();
|
|
||||||
public VHatCanIRoll() {
|
public VHatCanIRoll() {
|
||||||
ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, Config.SPEC);
|
ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, Config.SPEC);
|
||||||
MinecraftForge.EVENT_BUS.register(this);
|
MinecraftForge.EVENT_BUS.register(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<ItemStack> 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<ItemStack> getWoldGearItems() {
|
|
||||||
List<ItemStack> woldItems = new ArrayList<>();
|
|
||||||
List<String> 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;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
87
src/main/java/com/radimous/vhatcaniroll/logic/Items.java
Normal file
87
src/main/java/com/radimous/vhatcaniroll/logic/Items.java
Normal file
|
|
@ -0,0 +1,87 @@
|
||||||
|
package com.radimous.vhatcaniroll.logic;
|
||||||
|
|
||||||
|
import iskallia.vault.gear.VaultGearState;
|
||||||
|
import iskallia.vault.gear.data.VaultGearData;
|
||||||
|
import iskallia.vault.init.ModGearAttributes;
|
||||||
|
import iskallia.vault.init.ModItems;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.world.item.Item;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Items {
|
||||||
|
|
||||||
|
private static final List<ItemStack> GEAR_ITEMS = new ArrayList<>();
|
||||||
|
|
||||||
|
|
||||||
|
public static List<ItemStack> getVaultGearItems() {
|
||||||
|
if (GEAR_ITEMS.isEmpty()){
|
||||||
|
GEAR_ITEMS.addAll(getVHGearItems());
|
||||||
|
GEAR_ITEMS.addAll(getWoldGearItems());
|
||||||
|
}
|
||||||
|
return Collections.unmodifiableList(GEAR_ITEMS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<ItemStack> getVHGearItems() {
|
||||||
|
return List.of(
|
||||||
|
withTransmog(new ItemStack(ModItems.SWORD), new ResourceLocation("the_vault:gear/sword/sword_0")),
|
||||||
|
withTransmog(new ItemStack(ModItems.AXE), new ResourceLocation("the_vault:gear/axe/axe_0")),
|
||||||
|
withTransmog(new ItemStack(ModItems.HELMET), new ResourceLocation("the_vault:gear/armor/gladiator_dark/helmet")),
|
||||||
|
withTransmog(new ItemStack(ModItems.CHESTPLATE), new ResourceLocation("the_vault:gear/armor/magmatic/chestplate")),
|
||||||
|
withTransmog(new ItemStack(ModItems.LEGGINGS), new ResourceLocation("the_vault:gear/armor/reinforced_platemail_dark/leggings")),
|
||||||
|
withTransmog(new ItemStack(ModItems.BOOTS), new ResourceLocation("the_vault:gear/armor/gladiator_dark/boots")),
|
||||||
|
withTransmog(new ItemStack(ModItems.FOCUS), new ResourceLocation("the_vault:gear/focus/tatteredtome")),
|
||||||
|
withTransmog(new ItemStack(ModItems.SHIELD), new ResourceLocation("the_vault:gear/shield/gold_plated")),
|
||||||
|
withTransmog(new ItemStack(ModItems.WAND), new ResourceLocation("the_vault:gear/wand/lunar")),
|
||||||
|
withTransmog(new ItemStack(ModItems.MAGNET), new ResourceLocation("the_vault:magnets/magnet_1")),
|
||||||
|
withTransmog(new ItemStack(ModItems.JEWEL), new ResourceLocation("the_vault:gear/jewel/sword_0"))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<ItemStack> getWoldGearItems() {
|
||||||
|
List<ItemStack> woldItems = new ArrayList<>();
|
||||||
|
List<Pair<String, String>> woldItemFields = Arrays.asList(
|
||||||
|
Pair.of("BATTLESTAFF", "the_vault:gear/battlestaff/battlestaff_redstone"),
|
||||||
|
Pair.of("TRIDENT", "the_vault:gear/trident/orange"),
|
||||||
|
Pair.of("PLUSHIE", "the_vault:gear/plushie/hrry"),
|
||||||
|
Pair.of("LOOT_SACK", "the_vault:gear/loot_sack/bundle"),
|
||||||
|
Pair.of("RANG", "the_vault:gear/rang/wooden")
|
||||||
|
);
|
||||||
|
try{
|
||||||
|
Class<?> woldItemClass = Class.forName("xyz.iwolfking.woldsvaults.init.ModItems");
|
||||||
|
for (Pair<String, String> woldFieldTransmogs : woldItemFields) {
|
||||||
|
try {
|
||||||
|
String woldFieldName = woldFieldTransmogs.getLeft();
|
||||||
|
Item item = (Item) woldItemClass.getField(woldFieldName).get(null);
|
||||||
|
woldItems.add(withTransmog(new ItemStack(item), new ResourceLocation(woldFieldTransmogs.getRight())));
|
||||||
|
} catch (IllegalArgumentException | SecurityException | NoSuchFieldException |
|
||||||
|
IllegalAccessException ignored) {
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (ClassNotFoundException ignored) {
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
|
return woldItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates copy of the given stack with the transmog applied
|
||||||
|
* @param stack the stack to apply the transmog to
|
||||||
|
* @param transmog the transmog to apply
|
||||||
|
* @return the stack with the transmog applied
|
||||||
|
*/
|
||||||
|
public static ItemStack withTransmog(ItemStack stack, ResourceLocation transmog){
|
||||||
|
ItemStack displayStack = stack.copy();
|
||||||
|
VaultGearData gearData = VaultGearData.read(displayStack);
|
||||||
|
gearData.setState(VaultGearState.IDENTIFIED);
|
||||||
|
gearData.createOrReplaceAttributeValue(ModGearAttributes.GEAR_MODEL, transmog);
|
||||||
|
gearData.write(displayStack);
|
||||||
|
return displayStack;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
package com.radimous.vhatcaniroll.logic;
|
||||||
|
|
||||||
|
import net.minecraft.ChatFormatting;
|
||||||
|
import net.minecraft.network.chat.Style;
|
||||||
|
import net.minecraft.network.chat.TextColor;
|
||||||
|
|
||||||
|
public enum ModifierCategory {
|
||||||
|
NORMAL,
|
||||||
|
GREATER,
|
||||||
|
LEGENDARY;
|
||||||
|
|
||||||
|
public String getSymbol() {
|
||||||
|
return "✦";
|
||||||
|
// greater is not full width :(
|
||||||
|
// return switch (this) {
|
||||||
|
// case NORMAL -> "";
|
||||||
|
// case GREATER -> "⧫";
|
||||||
|
// case LEGENDARY -> "✦";
|
||||||
|
// };
|
||||||
|
}
|
||||||
|
|
||||||
|
public Style getStyle() {
|
||||||
|
return switch (this) {
|
||||||
|
case NORMAL -> Style.EMPTY.withColor(ChatFormatting.WHITE);
|
||||||
|
case GREATER -> Style.EMPTY.withColor(TextColor.fromRgb(5886486));
|
||||||
|
case LEGENDARY -> Style.EMPTY.withColor(ChatFormatting.GOLD);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTierIncrease() {
|
||||||
|
return switch (this) {
|
||||||
|
case NORMAL -> 0;
|
||||||
|
case GREATER -> 1;
|
||||||
|
case LEGENDARY -> 2;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public ModifierCategory next() {
|
||||||
|
return values()[(this.ordinal() + 1) % values().length];
|
||||||
|
}
|
||||||
|
|
||||||
|
public ModifierCategory previous() {
|
||||||
|
return values()[(this.ordinal() + values().length - 1) % values().length];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
554
src/main/java/com/radimous/vhatcaniroll/logic/Modifiers.java
Normal file
554
src/main/java/com/radimous/vhatcaniroll/logic/Modifiers.java
Normal file
|
|
@ -0,0 +1,554 @@
|
||||||
|
package com.radimous.vhatcaniroll.logic;
|
||||||
|
|
||||||
|
import com.radimous.vhatcaniroll.Config;
|
||||||
|
import com.radimous.vhatcaniroll.mixin.AbilityFloatValueAttributeReaderInvoker;
|
||||||
|
import com.radimous.vhatcaniroll.mixin.EffectConfigAccessor;
|
||||||
|
import com.radimous.vhatcaniroll.mixin.VaultGearTierConfigAccessor;
|
||||||
|
import iskallia.vault.config.UniqueGearConfig;
|
||||||
|
import iskallia.vault.config.gear.VaultGearTierConfig;
|
||||||
|
import iskallia.vault.gear.attribute.VaultGearAttribute;
|
||||||
|
import iskallia.vault.gear.attribute.VaultGearAttributeRegistry;
|
||||||
|
import iskallia.vault.gear.attribute.VaultGearModifier;
|
||||||
|
import iskallia.vault.gear.attribute.ability.AbilityAreaOfEffectPercentAttribute;
|
||||||
|
import iskallia.vault.gear.attribute.ability.AbilityLevelAttribute;
|
||||||
|
import iskallia.vault.gear.attribute.ability.special.EntropyPoisonModification;
|
||||||
|
import iskallia.vault.gear.attribute.ability.special.FrostNovaVulnerabilityModification;
|
||||||
|
import iskallia.vault.gear.attribute.ability.special.base.SpecialAbilityConfig;
|
||||||
|
import iskallia.vault.gear.attribute.ability.special.base.SpecialAbilityGearAttribute;
|
||||||
|
import iskallia.vault.gear.attribute.ability.special.base.SpecialAbilityModification;
|
||||||
|
import iskallia.vault.gear.attribute.ability.special.base.template.FloatRangeModification;
|
||||||
|
import iskallia.vault.gear.attribute.ability.special.base.template.IntRangeModification;
|
||||||
|
import iskallia.vault.gear.attribute.ability.special.base.template.config.FloatRangeConfig;
|
||||||
|
import iskallia.vault.gear.attribute.ability.special.base.template.config.IntRangeConfig;
|
||||||
|
import iskallia.vault.gear.attribute.ability.special.base.template.value.FloatValue;
|
||||||
|
import iskallia.vault.gear.attribute.ability.special.base.template.value.IntValue;
|
||||||
|
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.gear.attribute.custom.loot.LootTriggerAttribute;
|
||||||
|
import iskallia.vault.gear.attribute.custom.loot.ManaPerLootAttribute;
|
||||||
|
import iskallia.vault.gear.reader.VaultGearModifierReader;
|
||||||
|
import iskallia.vault.init.ModConfigs;
|
||||||
|
import iskallia.vault.skill.ability.component.AbilityLabelFormatters;
|
||||||
|
import iskallia.vault.skill.base.Skill;
|
||||||
|
import net.minecraft.ChatFormatting;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.network.chat.MutableComponent;
|
||||||
|
import net.minecraft.network.chat.Style;
|
||||||
|
import net.minecraft.network.chat.TextColor;
|
||||||
|
import net.minecraft.network.chat.TextComponent;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraftforge.fml.LogicalSide;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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};
|
||||||
|
|
||||||
|
private static final Pattern CLOUD_PATTERN = Pattern.compile("^(?<effect>.*?) ?(?<lvl>I|II|III|IV|V|VI|VII|VIII|IX|X)? (?<suffix>Cloud.*)$");
|
||||||
|
private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("0.##");
|
||||||
|
|
||||||
|
public static List<Component> getModifierList(int lvl, VaultGearTierConfig cfg, ModifierCategory modifierCategory) {
|
||||||
|
Map<VaultGearTierConfig.ModifierAffixTagGroup, VaultGearTierConfig.AttributeGroup> modifierGroup = ((VaultGearTierConfigAccessor) cfg).getModifierGroup();
|
||||||
|
|
||||||
|
ArrayList<Component> modList = new ArrayList<>();
|
||||||
|
|
||||||
|
for (VaultGearTierConfig.ModifierAffixTagGroup affixTagGroup : modifierGroup.keySet()) {
|
||||||
|
modList.addAll(getAffixGroupComponents(lvl, affixTagGroup, modifierGroup.get(affixTagGroup), modifierCategory));
|
||||||
|
}
|
||||||
|
|
||||||
|
return modList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<Component> getUniqueModifierList(int lvl, ModifierCategory modifierCategory, Map<UniqueGearConfig.AffixTargetType, List<ResourceLocation>> modifierIdentifiers) {
|
||||||
|
ArrayList<Component> modList = new ArrayList<>();
|
||||||
|
|
||||||
|
for (Map.Entry<UniqueGearConfig.AffixTargetType, List<ResourceLocation>> modifierIdentifier : modifierIdentifiers.entrySet()) {
|
||||||
|
modList.addAll(getUniqueAffixComponents(lvl, modifierIdentifier, modifierCategory));
|
||||||
|
}
|
||||||
|
|
||||||
|
return modList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<Component> getAffixGroupComponents(int lvl, VaultGearTierConfig.ModifierAffixTagGroup affixTagGroup,
|
||||||
|
VaultGearTierConfig.AttributeGroup modifierGroups,
|
||||||
|
ModifierCategory modifierCategory) {
|
||||||
|
|
||||||
|
ArrayList<Component> componentList = new ArrayList<>();
|
||||||
|
if (!Config.SHOW_ABILITY_ENHANCEMENTS.get() && affixTagGroup.equals(VaultGearTierConfig.ModifierAffixTagGroup.ABILITY_ENHANCEMENT)) {
|
||||||
|
return componentList;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Map<String, Integer> groupCounts = countGroups(lvl, modifierGroups, modifierCategory);
|
||||||
|
|
||||||
|
AtomicBoolean noWeightAttr = new AtomicBoolean(false);
|
||||||
|
int totalWeight = modifierGroups.stream()
|
||||||
|
.mapToInt(modTierGroup -> getModifierTiers(lvl, modTierGroup, modifierCategory).stream().mapToInt(
|
||||||
|
tier -> {
|
||||||
|
if ((affixTagGroup == VaultGearTierConfig.ModifierAffixTagGroup.IMPLICIT
|
||||||
|
|| affixTagGroup == VaultGearTierConfig.ModifierAffixTagGroup.BASE_ATTRIBUTES) && groupCounts.get(modTierGroup.getModifierGroup()) == 1) {
|
||||||
|
noWeightAttr.set(true);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return tier.getWeight();
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.sum())
|
||||||
|
.sum();
|
||||||
|
|
||||||
|
|
||||||
|
if (totalWeight == 0 && !noWeightAttr.get()) {
|
||||||
|
return componentList;
|
||||||
|
}
|
||||||
|
|
||||||
|
componentList.add(new TextComponent(affixTagGroup.toString().replace("_", " ")).withStyle(ChatFormatting.BOLD));
|
||||||
|
|
||||||
|
if (Config.SHOW_WEIGHT.get() && shouldShowWeight(modifierCategory, affixTagGroup) && totalWeight > 0) {
|
||||||
|
componentList.add(new TextComponent("Total Weight: " + totalWeight).withStyle(ChatFormatting.BOLD));
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, List<Component>> groupedModifiers = new HashMap<>();
|
||||||
|
for (VaultGearTierConfig.ModifierTierGroup modifierTierGroup :modifierGroups) {
|
||||||
|
ArrayList<VaultGearTierConfig.ModifierTier<?>> mTierList;
|
||||||
|
|
||||||
|
mTierList = getModifierTiers(lvl, modifierTierGroup, modifierCategory);
|
||||||
|
if (mTierList.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String modGr = modifierTierGroup.getModifierGroup();
|
||||||
|
|
||||||
|
|
||||||
|
MutableComponent modComp = getModifierComponent(VaultGearAttributeRegistry.getAttribute(modifierTierGroup.getAttribute()),mTierList);
|
||||||
|
|
||||||
|
if (!(
|
||||||
|
(affixTagGroup == VaultGearTierConfig.ModifierAffixTagGroup.BASE_ATTRIBUTES
|
||||||
|
|| affixTagGroup == VaultGearTierConfig.ModifierAffixTagGroup.IMPLICIT
|
||||||
|
)
|
||||||
|
&& groupCounts.get(modGr) == 1)){
|
||||||
|
int weight = modTierListWeight(mTierList);
|
||||||
|
if (Config.SHOW_WEIGHT.get() && shouldShowWeight(modifierCategory, affixTagGroup)) {
|
||||||
|
modComp.append(new TextComponent(" w"+weight).withStyle(ChatFormatting.GRAY));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.SHOW_CHANCE.get() && shouldShowWeight(modifierCategory, affixTagGroup) && totalWeight > 0) {
|
||||||
|
modComp.append(new TextComponent(String.format(" %.2f%%", ((double) weight * 100 / totalWeight))).withStyle(ChatFormatting.GRAY));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (groupCounts.get(modGr) > 1) {
|
||||||
|
groupedModifiers.computeIfAbsent(modGr, k -> new ArrayList<>()).add(modComp);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
MutableComponent full = new TextComponent(" ");
|
||||||
|
|
||||||
|
full.append(modComp);
|
||||||
|
|
||||||
|
componentList.add(full);
|
||||||
|
}
|
||||||
|
|
||||||
|
// more than 7 groups is a bit crazy, but just in case
|
||||||
|
boolean useNums = groupedModifiers.size() > COLORS.length;
|
||||||
|
int i = 0;
|
||||||
|
for (List<Component> modGr: groupedModifiers.values()) {
|
||||||
|
for (Component mod: modGr) {
|
||||||
|
MutableComponent full = new TextComponent(useNums ? i + " " : "► ").withStyle(COLORS[i % COLORS.length]);
|
||||||
|
full.append(mod);
|
||||||
|
componentList.add(full);
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
componentList.add(TextComponent.EMPTY);
|
||||||
|
return componentList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same as getAffixGroupComponents, but for unique gear without chances and groups
|
||||||
|
*/
|
||||||
|
public static List<Component> getUniqueAffixComponents(int lvl,Map.Entry<UniqueGearConfig.AffixTargetType, List<ResourceLocation>> modifierIdentifier, ModifierCategory modifierCategory) {
|
||||||
|
|
||||||
|
ArrayList<Component> componentList = new ArrayList<>();
|
||||||
|
if (modifierIdentifier.getValue().isEmpty()) {
|
||||||
|
return componentList; // no affix for this type
|
||||||
|
}
|
||||||
|
UniqueGearConfig.AffixTargetType affixTagGroup = modifierIdentifier.getKey();
|
||||||
|
componentList.add(new TextComponent(affixTagGroup.toString().replace("_", " ")).withStyle(ChatFormatting.BOLD));
|
||||||
|
for (ResourceLocation modifier : modifierIdentifier.getValue()) {
|
||||||
|
VaultGearTierConfig.ModifierTierGroup modifierTierGroup = ModConfigs.VAULT_GEAR_CONFIG.get(VaultGearTierConfig.UNIQUE_ITEM).getTierGroup(modifier);
|
||||||
|
if (modifierTierGroup == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ArrayList<VaultGearTierConfig.ModifierTier<?>> mTierList;
|
||||||
|
mTierList = getModifierTiers(lvl, modifierTierGroup, modifierCategory);
|
||||||
|
if (mTierList.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
MutableComponent modComp = getModifierComponent(VaultGearAttributeRegistry.getAttribute(modifierTierGroup.getAttribute()),mTierList);
|
||||||
|
MutableComponent full = new TextComponent(" ");
|
||||||
|
full.append(modComp);
|
||||||
|
componentList.add(full);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (componentList.size() == 1) { // only header
|
||||||
|
return new ArrayList<>(); // no affixes for this type (all tiers are unobtainable)
|
||||||
|
}
|
||||||
|
|
||||||
|
componentList.add(TextComponent.EMPTY);
|
||||||
|
return componentList;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<String, Integer> countGroups(int lvl, VaultGearTierConfig.AttributeGroup modifierTierGroups, ModifierCategory modifierCategory) {
|
||||||
|
Map<String, Integer> groupCounts = new HashMap<>();
|
||||||
|
for (VaultGearTierConfig.ModifierTierGroup modifierTierGroup : modifierTierGroups) {
|
||||||
|
ArrayList<VaultGearTierConfig.ModifierTier<?>> mTierList;
|
||||||
|
mTierList = getModifierTiers(lvl, modifierTierGroup, modifierCategory);
|
||||||
|
if (mTierList.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
groupCounts.put(modifierTierGroup.getModifierGroup(),
|
||||||
|
groupCounts.getOrDefault(modifierTierGroup.getModifierGroup(), 0) + 1);
|
||||||
|
}
|
||||||
|
return groupCounts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ArrayList<VaultGearTierConfig.ModifierTier<?>> getModifierTiers(int lvl, VaultGearTierConfig.ModifierTierGroup modifierTierGroup, ModifierCategory modifierCategory) {
|
||||||
|
|
||||||
|
if (modifierCategory == ModifierCategory.NORMAL) {
|
||||||
|
return getNormalModifierTiers(lvl, modifierTierGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayList<VaultGearTierConfig.ModifierTier<?>> res = new ArrayList<>();
|
||||||
|
VaultGearTierConfig.ModifierTier<?> highest = modifierTierGroup.getHighestForLevel(lvl);
|
||||||
|
if (highest == null) {
|
||||||
|
return res; // empty
|
||||||
|
}
|
||||||
|
if (modifierTierGroup.getTags().contains("noLegendary")){
|
||||||
|
return res; // empty
|
||||||
|
}
|
||||||
|
int index = Math.min(highest.getModifierTier() + modifierCategory.getTierIncrease(), modifierTierGroup.size() - 1);
|
||||||
|
VaultGearTierConfig.ModifierTier<?> legendTier = modifierTierGroup.get(index);
|
||||||
|
if (legendTier == null || legendTier.getWeight() == 0){
|
||||||
|
return res; // empty
|
||||||
|
}
|
||||||
|
if (legendTier.getModifierConfiguration() instanceof BooleanFlagGenerator.BooleanFlag bf &&
|
||||||
|
!bf.get()) {
|
||||||
|
return res; // empty
|
||||||
|
}
|
||||||
|
res.add(legendTier);
|
||||||
|
return res; // only one
|
||||||
|
}
|
||||||
|
@NotNull private static ArrayList<VaultGearTierConfig.ModifierTier<?>> getNormalModifierTiers(int lvl,
|
||||||
|
VaultGearTierConfig.ModifierTierGroup modifierTierGroup) {
|
||||||
|
return modifierTierGroup.getModifiersForLevel(lvl).stream()
|
||||||
|
.filter(x -> x.getWeight() != 0
|
||||||
|
&& !(x.getModifierConfiguration() instanceof BooleanFlagGenerator.BooleanFlag bf &&
|
||||||
|
!bf.get())) // bool with false :( looking at you, soulbound
|
||||||
|
.collect(Collectors.toCollection(ArrayList::new));
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked") // I don't think proper generics are possible, VaultGearTierConfig#getModifiersForLevel returns List<ModifierTier<?>>
|
||||||
|
public static <T, C> MutableComponent getModifierComponent(VaultGearAttribute<T> atr,
|
||||||
|
ArrayList<VaultGearTierConfig.ModifierTier<?>> modifierTiers) {
|
||||||
|
if (modifierTiers.isEmpty()) {
|
||||||
|
return new TextComponent("ERR - EMPTY MODIFIER TIERS");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (atr == null) {
|
||||||
|
return new TextComponent("ERR - NULL ATTRIBUTE");
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigurableAttributeGenerator<T, C> atrGenerator = (ConfigurableAttributeGenerator<T, C>) atr.getGenerator();
|
||||||
|
if (atrGenerator == null) {
|
||||||
|
return new TextComponent("ERR - NULL ATTRIBUTE GENERATOR");
|
||||||
|
}
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
String atrName = atrRegName.toString();
|
||||||
|
|
||||||
|
MutableComponent minConfigDisplay = atrGenerator.getConfigDisplay(atr.getReader(), minConfig);
|
||||||
|
|
||||||
|
if (minConfig instanceof SpecialAbilityGearAttribute.SpecialAbilityTierConfig<?,?,?> minConfigSpecial) {
|
||||||
|
return getSpecialAbilityAttributeComponent(modifierTiers, minConfigSpecial);
|
||||||
|
}
|
||||||
|
|
||||||
|
MutableComponent res = null;
|
||||||
|
if (modifierTiers.size() > 1) {
|
||||||
|
res = rangeComponent(atrName, atr, atrGenerator, minConfig, maxConfig);
|
||||||
|
if (res != null) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (minConfig instanceof AbilityAreaOfEffectPercentAttribute.Config minConfigA) {
|
||||||
|
return getAbilityAoePercentageComponent(atr, minConfigA, minConfigA);
|
||||||
|
}
|
||||||
|
if (minConfig instanceof ManaPerLootAttribute.Config maxManaPerLootConfig) {
|
||||||
|
return getManaPerLootComponent(maxManaPerLootConfig, maxManaPerLootConfig);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
return new TextComponent("ERR - NULL DISPLAY " + atrName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked") // this thing is insane
|
||||||
|
private static @NotNull MutableComponent getSpecialAbilityAttributeComponent(
|
||||||
|
ArrayList<VaultGearTierConfig.ModifierTier<?>> modifierTiers,
|
||||||
|
SpecialAbilityGearAttribute.SpecialAbilityTierConfig<?, ?, ?> minConfigSpecial) {
|
||||||
|
SpecialAbilityModification<? extends SpecialAbilityConfig<?>, ?> modification = minConfigSpecial.getModification();
|
||||||
|
if (modification instanceof IntRangeModification intRangeModification){
|
||||||
|
var minValue = intRangeModification.getMinimumValue(getIntTiers(modifierTiers));
|
||||||
|
var maxValue = intRangeModification.getMaximumValue(getIntTiers(modifierTiers));
|
||||||
|
String minValueDisplay = minValue.map(x -> String.valueOf(x.getValue().getValue())).orElse("NULL");
|
||||||
|
String maxValueDisplay = maxValue.map(x -> String.valueOf(x.getValue().getValue())).orElse("NULL");
|
||||||
|
MutableComponent minToMaxComponent = new TextComponent(minValueDisplay + "-" + maxValueDisplay).withStyle(ChatFormatting.UNDERLINE).withStyle(Style.EMPTY.withColor(TextColor.fromRgb(6082075)));
|
||||||
|
if (intRangeModification instanceof FrostNovaVulnerabilityModification) {
|
||||||
|
return (new TextComponent("Frost Nova also applies Level ").append(minToMaxComponent).append(" Vulnerability")).withStyle(Style.EMPTY.withColor(TextColor.fromRgb(14076214)));
|
||||||
|
}
|
||||||
|
if (intRangeModification instanceof EntropyPoisonModification) {
|
||||||
|
return new TextComponent("Entropic Bind also applies Poison ").withStyle(Style.EMPTY.withColor(TextColor.fromRgb(14076214))).append(minToMaxComponent);
|
||||||
|
}
|
||||||
|
if (intRangeModification.getKey().toString().equals("the_vault:glacial_blast_hypothermia")){
|
||||||
|
return (new TextComponent("Glacial Blast is ").append(minToMaxComponent).append("X more likely to shatter")).withStyle(Style.EMPTY.withColor(TextColor.fromRgb(14076214)));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if (modification instanceof FloatRangeModification floatRangeModification) {
|
||||||
|
var minValue = floatRangeModification.getMinimumValue(getFloatTiers(modifierTiers));
|
||||||
|
var maxValue = floatRangeModification.getMaximumValue(getFloatTiers(modifierTiers));
|
||||||
|
float minValueDisplay = minValue.map(x -> x.getValue().getValue()).orElse(0f);
|
||||||
|
float maxValueDisplay = maxValue.map(x -> x.getValue().getValue()).orElse(0f);
|
||||||
|
|
||||||
|
MutableComponent minToMaxComponent = new TextComponent(DECIMAL_FORMAT.format(minValueDisplay*100) + "%-" + DECIMAL_FORMAT.format(maxValueDisplay*100)+"%").withStyle(ChatFormatting.UNDERLINE).withStyle(Style.EMPTY.withColor(TextColor.fromRgb(6082075)));
|
||||||
|
if (floatRangeModification.getKey().toString().equals("the_vault:fireball_special_modification")){
|
||||||
|
return (new TextComponent("Fireball has ").append(minToMaxComponent).append(" chance to fire twice")).withStyle(Style.EMPTY.withColor(TextColor.fromRgb(14076214)));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String abilityKey = minConfigSpecial.getAbilityKey();
|
||||||
|
return ModConfigs.ABILITIES.getAbilityById(abilityKey).filter(skill -> skill.getName() != null).map(skill -> {
|
||||||
|
String name = skill.getName();
|
||||||
|
return new TextComponent("Special " + name + " modification");
|
||||||
|
}).orElseGet(() -> (TextComponent) new TextComponent(abilityKey).withStyle(Style.EMPTY.withColor(14076214)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private static List<SpecialAbilityGearAttribute.SpecialAbilityTierConfig<SpecialAbilityModification<IntRangeConfig, IntValue>, IntRangeConfig, IntValue>> getIntTiers(List<VaultGearTierConfig.ModifierTier<?>> modifierTiers) {
|
||||||
|
return modifierTiers.stream().map(x -> (SpecialAbilityGearAttribute.SpecialAbilityTierConfig<SpecialAbilityModification<IntRangeConfig, IntValue>, IntRangeConfig, IntValue>) x.getModifierConfiguration()).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private static List<SpecialAbilityGearAttribute.SpecialAbilityTierConfig<SpecialAbilityModification<FloatRangeConfig, FloatValue>, FloatRangeConfig, FloatValue>> getFloatTiers(List<VaultGearTierConfig.ModifierTier<?>> modifierTiers) {
|
||||||
|
return modifierTiers.stream().map(x -> (SpecialAbilityGearAttribute.SpecialAbilityTierConfig<SpecialAbilityModification<FloatRangeConfig, FloatValue>, FloatRangeConfig, FloatValue>) x.getModifierConfiguration()).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 <T, C> MutableComponent rangeComponent(String atrName, VaultGearAttribute<T> atr,
|
||||||
|
ConfigurableAttributeGenerator<T, C> atrGenerator, C minConfig, C maxConfig) {
|
||||||
|
MutableComponent res = atrGenerator.getConfigRangeDisplay(atr.getReader(), minConfig, maxConfig);
|
||||||
|
MutableComponent minConfigDisplay = atrGenerator.getConfigDisplay(atr.getReader(), minConfig);
|
||||||
|
MutableComponent maxConfigDisplay = atrGenerator.getConfigDisplay(atr.getReader(), maxConfig);
|
||||||
|
|
||||||
|
|
||||||
|
if (res != null && minConfig instanceof AbilityLevelAttribute.Config minConfigAbility) {
|
||||||
|
return abilityLvlComponent(res, atr, minConfigAbility);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((atrName.equals("the_vault:effect_avoidance") || atrName.equals("the_vault:effect_list_avoidance")) && minConfigDisplay != null) {
|
||||||
|
// res -> "30% - 50%"
|
||||||
|
// single -> "30% Poison Avoidance"
|
||||||
|
// minRange -> "30%"
|
||||||
|
MutableComponent single = minConfigDisplay.withStyle(atr.getReader().getColoredTextStyle());
|
||||||
|
MutableComponent minRange = atrGenerator.getConfigRangeDisplay(atr.getReader(), minConfig, minConfig);
|
||||||
|
if (minRange != null && res != null) {
|
||||||
|
res.append(single.getString().replace(minRange.getString(), ""));
|
||||||
|
// res -> "30% - 50% Poison Avoidance"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (minConfigDisplay != null && maxConfigDisplay != null && (atrName.equals("the_vault:effect_cloud") || atrName.equals("the_vault:effect_cloud_when_hit"))) {
|
||||||
|
return getCloudRangeComponent(minConfigDisplay, maxConfigDisplay, atr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((minConfig instanceof AbilityAreaOfEffectPercentAttribute.Config minConfigA) && (maxConfig instanceof AbilityAreaOfEffectPercentAttribute.Config maxConfigA)) {
|
||||||
|
return getAbilityAoePercentageComponent(atr, minConfigA, maxConfigA);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (minConfig instanceof EffectGearAttribute.Config minEffectConfig
|
||||||
|
&& maxConfig instanceof EffectGearAttribute.Config
|
||||||
|
&& maxConfigDisplay != null) {
|
||||||
|
String effectStr = ((EffectConfigAccessor)minEffectConfig).getAmplifier() + "-" +
|
||||||
|
maxConfigDisplay.getString();
|
||||||
|
return new TextComponent(effectStr).withStyle(atr.getReader().getColoredTextStyle());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (minConfig instanceof ManaPerLootAttribute.Config minManaPerLootConfig && maxConfig instanceof ManaPerLootAttribute.Config maxManaPerLootConfig) {
|
||||||
|
return getManaPerLootComponent(minManaPerLootConfig, maxManaPerLootConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (atrName.equals("the_vault:effect_cloud")){
|
||||||
|
return new TextComponent("Special ability modification");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res != null) {
|
||||||
|
return atr.getReader().formatConfigDisplay(LogicalSide.CLIENT, res);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static @NotNull MutableComponent getManaPerLootComponent(ManaPerLootAttribute.Config minManaPerLootConfig,
|
||||||
|
ManaPerLootAttribute.Config maxManaPerLootConfig) {
|
||||||
|
int minGenerated = minManaPerLootConfig.getManaGenerated().getMin();
|
||||||
|
int maxGenerated = maxManaPerLootConfig.getManaGenerated().getMax();
|
||||||
|
float minGenChance = minManaPerLootConfig.getManaGenerationChance().getMin();
|
||||||
|
float maxGenChance = maxManaPerLootConfig.getManaGenerationChance().getMax();
|
||||||
|
var minToMax = new TextComponent(DECIMAL_FORMAT.format(minGenChance*100) + "%-" + DECIMAL_FORMAT.format(maxGenChance*100) + "%").withStyle(Style.EMPTY.withColor(20479));
|
||||||
|
var generated = new TextComponent(minGenerated + "-" + maxGenerated).withStyle(Style.EMPTY.withColor(20479));
|
||||||
|
var loot = new TextComponent(maxManaPerLootConfig.getDisplayName()).withStyle(Style.EMPTY.withColor(20479));
|
||||||
|
return new TextComponent("").withStyle(Style.EMPTY.withColor(65535)).append(minToMax).append(new TextComponent(" chance to generate ")).append(generated).append(" Mana per ").append(loot).append(" looted");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T> @NotNull MutableComponent getAbilityAoePercentageComponent(VaultGearAttribute<T> atr,
|
||||||
|
AbilityAreaOfEffectPercentAttribute.Config minConfigA,
|
||||||
|
AbilityAreaOfEffectPercentAttribute.Config maxConfigA) {
|
||||||
|
float min = minConfigA.getMin();
|
||||||
|
float max = maxConfigA.generateMaximumValue();
|
||||||
|
|
||||||
|
VaultGearModifierReader<T> reader = atr.getReader();
|
||||||
|
MutableComponent minValueDisplay = new TextComponent(new DecimalFormat("0.#").format(Math.abs(min * 100.0F)) + "%");
|
||||||
|
MutableComponent maxValueDisplay = new TextComponent(new DecimalFormat("0.#").format(Math.abs(max * 100.0F)) + "%");
|
||||||
|
boolean positive = min > 0;
|
||||||
|
MutableComponent areaCmp = new TextComponent("Area Of Effect").withStyle(Style.EMPTY.withColor(ModConfigs.COLORS.getColor("areaOfEffect")));
|
||||||
|
String cdInfo;
|
||||||
|
if (positive) {
|
||||||
|
cdInfo = " more ";
|
||||||
|
} else {
|
||||||
|
cdInfo = " less ";
|
||||||
|
}
|
||||||
|
|
||||||
|
return new TextComponent("")
|
||||||
|
.append(VaultGearModifier.AffixType.IMPLICIT.getAffixPrefixComponent(true)
|
||||||
|
.withStyle(Style.EMPTY.withColor(6082075)))
|
||||||
|
.append(minValueDisplay.withStyle(Style.EMPTY.withColor(6082075)))
|
||||||
|
.append(new TextComponent("-").withStyle(Style.EMPTY.withColor(6082075)))
|
||||||
|
.append(maxValueDisplay.withStyle(Style.EMPTY.withColor(6082075)))
|
||||||
|
.append(cdInfo)
|
||||||
|
.append(areaCmp)
|
||||||
|
.append(" of ")
|
||||||
|
.append(
|
||||||
|
((AbilityFloatValueAttributeReaderInvoker) reader).invokeFormatAbilityName(minConfigA.getAbilityKey()))
|
||||||
|
.setStyle(reader.getColoredTextStyle());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static MutableComponent getCloudRangeComponent(MutableComponent minConfigDisplay, MutableComponent maxConfigDisplay, VaultGearAttribute<?> atr) {
|
||||||
|
// <Effect> [<LVL>] Cloud [when Hit]
|
||||||
|
// Poison Cloud
|
||||||
|
// Poison III Cloud
|
||||||
|
String minString = minConfigDisplay.getString();
|
||||||
|
String maxString = maxConfigDisplay.getString();
|
||||||
|
|
||||||
|
String minLvl = getCloudLvl(minString);
|
||||||
|
String maxLvl = getCloudLvl(maxString);
|
||||||
|
|
||||||
|
if (minLvl.equals(maxLvl)) {
|
||||||
|
return minConfigDisplay.withStyle(atr.getReader().getColoredTextStyle());
|
||||||
|
}
|
||||||
|
|
||||||
|
String cloudRange = makeCloudLvlRange(minString, minLvl, maxLvl);
|
||||||
|
return new TextComponent(cloudRange).withStyle(atr.getReader().getColoredTextStyle());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getCloudLvl(String displayString){
|
||||||
|
Matcher matcher = CLOUD_PATTERN.matcher(displayString);
|
||||||
|
if (matcher.find()) {
|
||||||
|
if (matcher.group("lvl") != null) {
|
||||||
|
return matcher.group("lvl");
|
||||||
|
}
|
||||||
|
return "I";
|
||||||
|
}
|
||||||
|
return "I";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String makeCloudLvlRange(String displayString, String minLvl, String maxLvl){
|
||||||
|
Matcher matcher = CLOUD_PATTERN.matcher(displayString);
|
||||||
|
if (matcher.find()) {
|
||||||
|
return matcher.group("effect") + " " + minLvl + "-" + maxLvl + " " + matcher.group("suffix");
|
||||||
|
}
|
||||||
|
return displayString;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static MutableComponent abilityLvlComponent(MutableComponent prev, VaultGearAttribute<?> atr,
|
||||||
|
AbilityLevelAttribute.Config minConfig) {
|
||||||
|
|
||||||
|
MutableComponent abComp = new TextComponent("+").withStyle(atr.getReader().getColoredTextStyle());
|
||||||
|
Optional<Skill> optSkill = ModConfigs.ABILITIES.getAbilityById(minConfig.getAbilityKey());
|
||||||
|
if (optSkill.isEmpty()) {
|
||||||
|
return prev.append(" added ability levels").withStyle(atr.getReader().getColoredTextStyle());
|
||||||
|
}
|
||||||
|
String abName = optSkill.get().getName();
|
||||||
|
String[] parts = prev.getString().split("-");
|
||||||
|
|
||||||
|
MutableComponent res = new TextComponent("").withStyle(prev.getStyle());
|
||||||
|
if (parts.length == 2) {
|
||||||
|
if (parts[0].equals(parts[1])) {
|
||||||
|
res.append(parts[0]);
|
||||||
|
} else {
|
||||||
|
res.append(parts[0]);
|
||||||
|
res.append("-");
|
||||||
|
res.append(parts[1]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
res.append(prev);
|
||||||
|
}
|
||||||
|
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<VaultGearTierConfig.ModifierTier<?>> val) {
|
||||||
|
if (val == null || val.isEmpty()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return val.stream().mapToInt(VaultGearTierConfig.ModifierTier::getWeight).sum();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean shouldShowWeight(ModifierCategory modifierCategory, VaultGearTierConfig.ModifierAffixTagGroup affixTagGroup) {
|
||||||
|
return modifierCategory == ModifierCategory.NORMAL && !Config.AFFIX_TAG_GROUP_CHANCE_BLACKLIST.get().contains(affixTagGroup.name());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
package com.radimous.vhatcaniroll.mixin;
|
||||||
|
|
||||||
|
import iskallia.vault.gear.attribute.ability.AbilityFloatValueAttribute;
|
||||||
|
import net.minecraft.network.chat.MutableComponent;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.gen.Invoker;
|
||||||
|
|
||||||
|
@Mixin(value = AbilityFloatValueAttribute.Reader.class, remap = false)
|
||||||
|
public interface AbilityFloatValueAttributeReaderInvoker {
|
||||||
|
@Invoker
|
||||||
|
MutableComponent invokeFormatAbilityName(String abilityKey);
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package com.radimous.vhatcaniroll.mixin;
|
package com.radimous.vhatcaniroll.mixin;
|
||||||
|
|
||||||
import iskallia.vault.gear.attribute.custom.EffectGearAttribute;
|
import iskallia.vault.gear.attribute.custom.effect.EffectGearAttribute;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
package com.radimous.vhatcaniroll.mixin;
|
package com.radimous.vhatcaniroll.mixin;
|
||||||
|
|
||||||
import com.radimous.vhatcaniroll.Config;
|
import com.radimous.vhatcaniroll.Config;
|
||||||
import com.radimous.vhatcaniroll.GearModifierScreen;
|
import com.radimous.vhatcaniroll.QOLHuntersCompat;
|
||||||
|
import com.radimous.vhatcaniroll.ui.GearModifierScreen;
|
||||||
import iskallia.vault.client.gui.framework.ScreenTextures;
|
import iskallia.vault.client.gui.framework.ScreenTextures;
|
||||||
import iskallia.vault.client.gui.framework.element.ButtonElement;
|
import iskallia.vault.client.gui.framework.element.ButtonElement;
|
||||||
import iskallia.vault.client.gui.framework.element.FakeItemSlotElement;
|
import iskallia.vault.client.gui.framework.element.FakeItemSlotElement;
|
||||||
|
|
@ -42,6 +43,8 @@ public class StatisticsElementContainerScreenMixin extends AbstractSkillTabEleme
|
||||||
|
|
||||||
// TODO: figure out how to add button like the quest button, not this ugly shit
|
// TODO: figure out how to add button like the quest button, not this ugly shit
|
||||||
|
|
||||||
|
QOLHuntersCompat.resolveQOLHuntersButtonConflict();
|
||||||
|
|
||||||
// add blank button to vault screen
|
// add blank button to vault screen
|
||||||
this.addElement(
|
this.addElement(
|
||||||
new ButtonElement<>(Spatials.positionXY(-3, 3), ScreenTextures.BUTTON_EMPTY_16_TEXTURES, () -> {
|
new ButtonElement<>(Spatials.positionXY(-3, 3), ScreenTextures.BUTTON_EMPTY_16_TEXTURES, () -> {
|
||||||
|
|
@ -56,8 +59,9 @@ public class StatisticsElementContainerScreenMixin extends AbstractSkillTabEleme
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
// add chestplate icon to it
|
// add chestplate icon to it
|
||||||
|
ItemStack chestplateStack = new ItemStack(ModItems.CHESTPLATE);
|
||||||
this.addElement(
|
this.addElement(
|
||||||
new FakeItemSlotElement<>(Spatials.positionXY(-3, 3), () -> new ItemStack(ModItems.CHESTPLATE), () -> false, ScreenTextures.EMPTY, ScreenTextures.EMPTY
|
new FakeItemSlotElement<>(Spatials.positionXY(-3, 3), () -> chestplateStack, () -> false, ScreenTextures.EMPTY, ScreenTextures.EMPTY
|
||||||
).layout(
|
).layout(
|
||||||
(screen, gui, parent, world) -> world.width(21).height(21).translateX(gui.right() + Config.BUTTON_X.get()).translateY(this.getTabContentSpatial().bottom() + Config.BUTTON_Y.get())
|
(screen, gui, parent, world) -> world.width(21).height(21).translateX(gui.right() + Config.BUTTON_X.get()).translateY(this.getTabContentSpatial().bottom() + Config.BUTTON_Y.get())
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
package com.radimous.vhatcaniroll.mixin;
|
||||||
|
|
||||||
|
import iskallia.vault.config.UniqueGearConfig;
|
||||||
|
import iskallia.vault.core.util.WeightedList;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Mixin(value = UniqueGearConfig.class, remap = false)
|
||||||
|
public interface UniqueGearConfigAccessor {
|
||||||
|
@Accessor
|
||||||
|
Map<ResourceLocation, UniqueGearConfig.Entry> getRegistry();
|
||||||
|
|
||||||
|
@Accessor
|
||||||
|
Map<ResourceLocation, WeightedList<ResourceLocation>> getPools();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,250 @@
|
||||||
|
package com.radimous.vhatcaniroll.ui;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import com.radimous.vhatcaniroll.Config;
|
||||||
|
import com.radimous.vhatcaniroll.logic.ModifierCategory;
|
||||||
|
import iskallia.vault.client.atlas.TextureAtlasRegion;
|
||||||
|
import iskallia.vault.client.gui.framework.ScreenTextures;
|
||||||
|
import iskallia.vault.client.gui.framework.element.ButtonElement;
|
||||||
|
import iskallia.vault.client.gui.framework.element.DynamicLabelElement;
|
||||||
|
import iskallia.vault.client.gui.framework.element.FakeItemSlotElement;
|
||||||
|
import iskallia.vault.client.gui.framework.element.LabelElement;
|
||||||
|
import iskallia.vault.client.gui.framework.element.NineSliceButtonElement;
|
||||||
|
import iskallia.vault.client.gui.framework.element.VerticalScrollClipContainer;
|
||||||
|
import iskallia.vault.client.gui.framework.render.spi.IElementRenderer;
|
||||||
|
import iskallia.vault.client.gui.framework.screen.layout.ScreenLayout;
|
||||||
|
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.config.gear.VaultGearWorkbenchConfig;
|
||||||
|
import iskallia.vault.gear.VaultGearState;
|
||||||
|
import iskallia.vault.gear.attribute.VaultGearModifier;
|
||||||
|
import iskallia.vault.gear.data.VaultGearData;
|
||||||
|
import iskallia.vault.init.ModGearAttributes;
|
||||||
|
import net.minecraft.ChatFormatting;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.player.LocalPlayer;
|
||||||
|
import net.minecraft.network.chat.MutableComponent;
|
||||||
|
import net.minecraft.network.chat.Style;
|
||||||
|
import net.minecraft.network.chat.TextColor;
|
||||||
|
import net.minecraft.network.chat.TextComponent;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import net.minecraft.world.item.Items;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import static iskallia.vault.client.gui.framework.ScreenTextures.BUTTON_EMPTY;
|
||||||
|
import static iskallia.vault.client.gui.framework.ScreenTextures.BUTTON_EMPTY_16_48_TEXTURES;
|
||||||
|
import static iskallia.vault.client.gui.framework.ScreenTextures.BUTTON_EMPTY_DISABLED;
|
||||||
|
|
||||||
|
|
||||||
|
public class CraftedModifiersListContainer extends VerticalScrollClipContainer<CraftedModifiersListContainer>
|
||||||
|
implements InnerGearScreen {
|
||||||
|
|
||||||
|
public CraftedModifiersListContainer(ISpatial spatial, int lvl, ModifierCategory modifierCategory,
|
||||||
|
ItemStack gearPiece) {
|
||||||
|
super(spatial);
|
||||||
|
int labelX = 9;
|
||||||
|
int labelY = 0;
|
||||||
|
|
||||||
|
LocalPlayer player = Minecraft.getInstance().player;
|
||||||
|
if (player == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemStack stackCopy = gearPiece.copy();
|
||||||
|
VaultGearData gearData = VaultGearData.read(stackCopy);
|
||||||
|
gearData.setItemLevel(lvl);
|
||||||
|
gearData.setState(VaultGearState.IDENTIFIED);
|
||||||
|
gearData.createOrReplaceAttributeValue(ModGearAttributes.PREFIXES, 1);
|
||||||
|
gearData.createOrReplaceAttributeValue(ModGearAttributes.SUFFIXES, 1);
|
||||||
|
gearData.write(stackCopy);
|
||||||
|
|
||||||
|
|
||||||
|
List<VaultGearWorkbenchConfig.CraftableModifierConfig> crMods = VaultGearWorkbenchConfig.getConfig(gearPiece.getItem())
|
||||||
|
.map(VaultGearWorkbenchConfig::getAllCraftableModifiers).orElse(null);
|
||||||
|
if (crMods == null) {
|
||||||
|
cookieDialog();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (VaultGearWorkbenchConfig.CraftableModifierConfig mod : crMods) {
|
||||||
|
boolean disabled = false;
|
||||||
|
|
||||||
|
// is unlocked?
|
||||||
|
MutableComponent fullCmp = new TextComponent("");
|
||||||
|
VaultGearModifier<?> mm = mod.createModifier().orElse(null);
|
||||||
|
if (mm == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Optional<MutableComponent> oCfgDisplay = mm.getConfigDisplay(gearPiece);
|
||||||
|
oCfgDisplay.ifPresent(fullCmp::append);
|
||||||
|
MutableComponent restriction = new TextComponent("");
|
||||||
|
int minLevel = mod.getMinLevel();
|
||||||
|
if (mod.getUnlockCategory() == VaultGearWorkbenchConfig.UnlockCategory.LEVEL && lvl < minLevel) {
|
||||||
|
if (!Config.SHOW_UNOBTAINABLE_CRAFTED.get()){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
restriction.append(new TextComponent(" LVL " + minLevel + "+").withStyle(ChatFormatting.DARK_RED));
|
||||||
|
disabled = true;
|
||||||
|
}
|
||||||
|
if (mod.getUnlockCategory() == VaultGearWorkbenchConfig.UnlockCategory.VAULT_DISCOVERY && !mod.hasPrerequisites(player)) {
|
||||||
|
if (minLevel > lvl) {
|
||||||
|
if (!Config.SHOW_UNOBTAINABLE_CRAFTED.get()){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
restriction.append(new TextComponent(" ARCHIVE").withStyle(ChatFormatting.DARK_RED));
|
||||||
|
} else {
|
||||||
|
restriction.append(new TextComponent(" ARCHIVE").withStyle(Style.EMPTY.withColor(TextColor.parseColor("#ff6f00"))));
|
||||||
|
}
|
||||||
|
disabled = true;
|
||||||
|
}
|
||||||
|
LabelElement<?> labelelement = new LabelElement<>(
|
||||||
|
Spatials.positionXY(8, labelY + 5).width(this.innerHeight() - labelX), fullCmp,
|
||||||
|
LabelTextStyle.defaultStyle().shadow() // WHY DOESN'T SHADOW WORK?
|
||||||
|
);
|
||||||
|
NineSliceButtonElement<?> btn = new NineSliceButtonElement<>(Spatials.positionXY(0, labelY ).width(innerWidth()).height(18),
|
||||||
|
new NineSliceButtonElement.NineSliceButtonTextures(BUTTON_EMPTY, BUTTON_EMPTY, BUTTON_EMPTY, BUTTON_EMPTY_DISABLED), () -> {});
|
||||||
|
|
||||||
|
|
||||||
|
//align right
|
||||||
|
LabelElement<?> restrictionLabel = new LabelElement<>(
|
||||||
|
Spatials.positionXY(btn.right() - 70, labelY + 5).width(this.innerHeight() - labelX).height(14), restriction,
|
||||||
|
LabelTextStyle.defaultStyle().border4()
|
||||||
|
);
|
||||||
|
btn.setDisabled(disabled);
|
||||||
|
this.addElement(btn);
|
||||||
|
this.addElement(labelelement);
|
||||||
|
this.addElement(restrictionLabel);
|
||||||
|
labelY += 18;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getScroll() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setScroll(float scroll) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InnerGearScreen create(ISpatial spatial, int lvl, ModifierCategory modifierCategory, ItemStack gearPiece) {
|
||||||
|
return new CraftedModifiersListContainer(spatial, lvl, modifierCategory, gearPiece);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// :)
|
||||||
|
private void cookieDialog(){
|
||||||
|
var noModifiers = new LabelElement<>(Spatials.positionXY(innerWidth()/2 - 60, 20).width(18).height(18), new TextComponent("No crafted modifiers found."), LabelTextStyle.defaultStyle().border4().center());
|
||||||
|
var wantCookie = new LabelElement<>(Spatials.positionXY(innerWidth()/2 - 50, 80).width(18).height(18), new TextComponent("Would you like a cookie?"), LabelTextStyle.defaultStyle().border4().center());
|
||||||
|
var yesBtn = new ButtonElement<>(Spatials.positionXY(innerWidth()/2 - 20, 100).width(100).height(20), BUTTON_EMPTY_16_48_TEXTURES, () -> {});
|
||||||
|
var noBtn = new ButtonElement<>(Spatials.positionXY(innerWidth()/2 - 20, 120).width(100).height(20), BUTTON_EMPTY_16_48_TEXTURES, () -> { /* sad cookie monster noises */});
|
||||||
|
var yesLabel = new LabelElement<>(Spatials.positionXY(innerWidth()/2 - 6, 105).width(18).height(18), new TextComponent("Yes"), LabelTextStyle.defaultStyle().border4().center());
|
||||||
|
var noLabel = new LabelElement<>(Spatials.positionXY(innerWidth()/2 - 3, 125).width(18).height(18), new TextComponent("No"), LabelTextStyle.defaultStyle().border4().center());
|
||||||
|
var sadCookie = new LabelElement<>(Spatials.positionXY(innerWidth()/2 - 65, 145).width(18).height(18), new TextComponent("*Sad cookie monster noises*").withStyle(ChatFormatting.GRAY), LabelTextStyle.defaultStyle().center());
|
||||||
|
yesBtn.setOnClick(() -> {
|
||||||
|
this.removeElement(noModifiers);
|
||||||
|
this.removeElement(wantCookie);
|
||||||
|
this.removeElement(yesBtn);
|
||||||
|
this.removeElement(noBtn);
|
||||||
|
this.removeElement(yesLabel);
|
||||||
|
this.removeElement(noLabel);
|
||||||
|
this.removeElement(sadCookie);
|
||||||
|
ScreenLayout.requestLayout();
|
||||||
|
cookie();
|
||||||
|
});
|
||||||
|
|
||||||
|
noBtn.setOnClick(() -> {
|
||||||
|
this.addElement(sadCookie);
|
||||||
|
noBtn.setDisabled(true);
|
||||||
|
ScreenLayout.requestLayout();
|
||||||
|
});
|
||||||
|
this.addElement(noModifiers);
|
||||||
|
this.addElement(wantCookie);
|
||||||
|
this.addElement(yesLabel);
|
||||||
|
this.addElement(noLabel);
|
||||||
|
this.addElement(noBtn);
|
||||||
|
this.addElement(yesBtn);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
private void cookie(){
|
||||||
|
AtomicInteger counter = new AtomicInteger(0);
|
||||||
|
var slot = new ScaledFakeItemSlotElement<>(Spatials.positionXY(innerWidth()/2, innerHeight()/2), () -> new ItemStack(Items.COOKIE), () -> false, ScreenTextures.EMPTY, ScreenTextures.EMPTY,8*16,8*16, 8f);
|
||||||
|
slot.whenClicked(counter::getAndIncrement);
|
||||||
|
this.addElement(slot);
|
||||||
|
this.addElement(new CookieLabelElement(Spatials.positionXY(innerWidth()/2, innerHeight()/2 - 70).width(18).height(18), counter::get, LabelTextStyle.defaultStyle().border4().center()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private class CookieLabelElement extends DynamicLabelElement<Integer, CookieLabelElement>{
|
||||||
|
public CookieLabelElement(IPosition position,
|
||||||
|
Supplier<Integer> valueSupplier, LabelTextStyle.Builder labelTextStyle) {
|
||||||
|
super(position, valueSupplier, labelTextStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override protected void onValueChanged(Integer count) {
|
||||||
|
this.set(new TextComponent(count.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void render(IElementRenderer renderer, @NotNull PoseStack poseStack, int mouseX, int mouseY,
|
||||||
|
float partialTick) {
|
||||||
|
if (this.valueSupplier.get() == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
PoseStack viewStack = RenderSystem.getModelViewStack();
|
||||||
|
viewStack.pushPose();
|
||||||
|
float scale = 2f;
|
||||||
|
viewStack.scale(scale, scale, scale);
|
||||||
|
viewStack.translate(-getWorldSpatial().x() * (1 - 1/scale), -getWorldSpatial().y() * (1 - 1/scale), 0);
|
||||||
|
RenderSystem.applyModelViewMatrix();
|
||||||
|
|
||||||
|
super.render(renderer, poseStack, mouseX, mouseY, partialTick);
|
||||||
|
viewStack.popPose();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ScaledFakeItemSlotElement <E extends ScaledFakeItemSlotElement<E>> extends FakeItemSlotElement<E> {
|
||||||
|
private float scale;
|
||||||
|
private long lastClicked = 0;
|
||||||
|
public ScaledFakeItemSlotElement(ISpatial spatial, Supplier<ItemStack> itemStack, Supplier<Boolean> disabled, TextureAtlasRegion slotTexture, TextureAtlasRegion disabledSlotTexture, int width, int height, float scale) {
|
||||||
|
super(Spatials.positionX((int) (spatial.x() - (scale * 9))).positionY((int) (spatial.y() - (scale * 9))), itemStack, disabled, slotTexture, disabledSlotTexture, width, height);
|
||||||
|
this.scale = scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void render(IElementRenderer renderer, @NotNull PoseStack poseStack, int mouseX, int mouseY, float partialTick) {
|
||||||
|
float originalScale = scale;
|
||||||
|
long msDiff = System.currentTimeMillis() - lastClicked;
|
||||||
|
if (msDiff < 150) {
|
||||||
|
scale *= 1 + msDiff * 0.001f;
|
||||||
|
} else if (msDiff < 300) {
|
||||||
|
scale *= 1 + (300 - msDiff) * 0.001f;
|
||||||
|
}
|
||||||
|
PoseStack viewStack = RenderSystem.getModelViewStack();
|
||||||
|
viewStack.pushPose();
|
||||||
|
viewStack.translate(- (scale - originalScale) * originalScale, - (scale - originalScale) * originalScale, 0);
|
||||||
|
viewStack.scale(scale, scale, 1);
|
||||||
|
viewStack.translate(-getWorldSpatial().x() * (1 - 1/scale), -getWorldSpatial().y() * (1 - 1/scale), 0);
|
||||||
|
RenderSystem.applyModelViewMatrix();
|
||||||
|
super.render(renderer, poseStack, mouseX, mouseY, partialTick);
|
||||||
|
viewStack.popPose();
|
||||||
|
scale = originalScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public boolean mouseClicked(double mouseX, double mouseY, int buttonIndex) {
|
||||||
|
if (this.isEnabled() && this.containsMouse(mouseX, mouseY) && buttonIndex == 0)
|
||||||
|
lastClicked = System.currentTimeMillis();
|
||||||
|
return super.mouseClicked(mouseX, mouseY, buttonIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,508 @@
|
||||||
|
package com.radimous.vhatcaniroll.ui;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.platform.InputConstants;
|
||||||
|
import com.radimous.vhatcaniroll.Config;
|
||||||
|
import com.radimous.vhatcaniroll.VHatCanIRoll;
|
||||||
|
import com.radimous.vhatcaniroll.logic.Items;
|
||||||
|
|
||||||
|
import com.radimous.vhatcaniroll.logic.ModifierCategory;
|
||||||
|
import com.simibubi.create.foundation.config.ui.ConfigScreen;
|
||||||
|
import com.simibubi.create.foundation.config.ui.SubMenuConfigScreen;
|
||||||
|
import iskallia.vault.client.gui.framework.ScreenRenderers;
|
||||||
|
import iskallia.vault.client.gui.framework.ScreenTextures;
|
||||||
|
import iskallia.vault.client.gui.framework.element.ButtonElement;
|
||||||
|
import iskallia.vault.client.gui.framework.element.FakeItemSlotElement;
|
||||||
|
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.TextureAtlasElement;
|
||||||
|
import iskallia.vault.client.gui.framework.element.VerticalScrollClipContainer;
|
||||||
|
import iskallia.vault.client.gui.framework.element.spi.ILayoutElement;
|
||||||
|
import iskallia.vault.client.gui.framework.element.spi.ILayoutStrategy;
|
||||||
|
import iskallia.vault.client.gui.framework.render.ScreenTooltipRenderer;
|
||||||
|
import iskallia.vault.client.gui.framework.render.TooltipDirection;
|
||||||
|
import iskallia.vault.client.gui.framework.render.Tooltips;
|
||||||
|
import iskallia.vault.client.gui.framework.screen.AbstractElementScreen;
|
||||||
|
import iskallia.vault.client.gui.framework.screen.layout.ScreenLayout;
|
||||||
|
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.gear.VaultGearState;
|
||||||
|
import iskallia.vault.gear.data.VaultGearData;
|
||||||
|
import iskallia.vault.init.ModBlocks;
|
||||||
|
import iskallia.vault.init.ModGearAttributes;
|
||||||
|
import iskallia.vault.init.ModItems;
|
||||||
|
import net.minecraft.ChatFormatting;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.network.chat.TextComponent;
|
||||||
|
import net.minecraft.network.chat.TranslatableComponent;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import net.minecraftforge.fml.config.ModConfig;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class GearModifierScreen extends AbstractElementScreen {
|
||||||
|
//TODO: remove magic numbers
|
||||||
|
private InnerGearScreen innerScreen;
|
||||||
|
private NineSliceButtonElement<?> minusButton;
|
||||||
|
private NineSliceButtonElement<?> plusButton;
|
||||||
|
private LabelElement<?> minusLabel;
|
||||||
|
private LabelElement<?> plusLabel;
|
||||||
|
private final ScrollableLvlInputElement lvlInput;
|
||||||
|
private ModifierCategory modifierCategory = ModifierCategory.NORMAL;
|
||||||
|
private LabelElement<?> modifierCategoryLabel;
|
||||||
|
private NineSliceButtonElement<?> modifierCategoryButton;
|
||||||
|
private final HelpContainer helpContainer;
|
||||||
|
private final LabelElement<?> windowNameLabel;
|
||||||
|
|
||||||
|
private int currIndex = 0;
|
||||||
|
private final List<TabElement<?>> tabs = new ArrayList<>();
|
||||||
|
|
||||||
|
public GearModifierScreen() {
|
||||||
|
super(new TextComponent("VHat can I roll?"), ScreenRenderers.getBuffered(), ScreenTooltipRenderer::create);
|
||||||
|
// make screen size 95% of the window height and width that looks good
|
||||||
|
this.setGuiSize(Spatials.size(340, 300).height((int) (
|
||||||
|
(Minecraft.getInstance().getWindow().getHeight() / Minecraft.getInstance().getWindow().getGuiScale()) *
|
||||||
|
0.95)));
|
||||||
|
|
||||||
|
// outer background
|
||||||
|
NineSliceElement<?> background = new NineSliceElement<>(
|
||||||
|
Spatials.positionXY(0, 30).size(this.getGuiSpatial().width(), this.getGuiSpatial().height() - 30),
|
||||||
|
ScreenTextures.DEFAULT_WINDOW_BACKGROUND
|
||||||
|
).layout(this.translateWorldSpatial());
|
||||||
|
|
||||||
|
// window title
|
||||||
|
LabelElement<?> windowName = new LabelElement<>(
|
||||||
|
Spatials.positionXY(7, 38).size(this.getGuiSpatial().width() / 2 - 7, 20),
|
||||||
|
new TranslatableComponent("vhatcaniroll.screen.title.random").withStyle(ChatFormatting.BLACK),
|
||||||
|
LabelTextStyle.defaultStyle()
|
||||||
|
).layout(this.translateWorldSpatial());
|
||||||
|
this.windowNameLabel = windowName;
|
||||||
|
|
||||||
|
this.addElement(background);
|
||||||
|
this.addElement(windowName);
|
||||||
|
|
||||||
|
createTabs();
|
||||||
|
|
||||||
|
this.lvlInput = this.addElement(createLvlInput());
|
||||||
|
|
||||||
|
createLvlButtons(lvlInput);
|
||||||
|
createModifierCategoryButton();
|
||||||
|
createConfigButton();
|
||||||
|
|
||||||
|
// inner black window
|
||||||
|
ISpatial modListSpatial = Spatials.positionXY(7, 50).size(this.getGuiSpatial().width() - 14, this.getGuiSpatial().height() - 57);
|
||||||
|
this.innerScreen = new ModifierListContainer(modListSpatial, lvlInput.getValue(), modifierCategory, getCurrGear()).layout(this.translateWorldSpatial());
|
||||||
|
this.addElement(this.innerScreen);
|
||||||
|
|
||||||
|
// help container will overlay the modifier list
|
||||||
|
this.helpContainer = new HelpContainer(Spatials.positionXY(0, 0).size(0, 0));
|
||||||
|
createHelpButton(helpContainer);
|
||||||
|
this.addElement(helpContainer);
|
||||||
|
|
||||||
|
createModifierButton();
|
||||||
|
createTransmogButton();
|
||||||
|
createCraftedModsButton();
|
||||||
|
createUniqueGearButton();
|
||||||
|
}
|
||||||
|
|
||||||
|
// helper methods
|
||||||
|
|
||||||
|
public ItemStack getCurrGear() {
|
||||||
|
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) {
|
||||||
|
float oldScroll = this.innerScreen.getScroll();
|
||||||
|
this.removeElement(this.innerScreen);
|
||||||
|
ISpatial modListSpatial = Spatials.positionXY(7, 50).size(this.getGuiSpatial().width() - 14, this.getGuiSpatial().height() - 57);
|
||||||
|
this.innerScreen = this.innerScreen.create(modListSpatial, lvlInput.getValue(), modifierCategory, getCurrGear());
|
||||||
|
if (this.innerScreen instanceof ILayoutElement<?> layoutElement) {
|
||||||
|
layoutElement.layout(this.translateWorldSpatial());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keepScroll) {
|
||||||
|
this.innerScreen.setScroll(oldScroll);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.addElement(this.innerScreen);
|
||||||
|
ScreenLayout.requestLayout();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void switchToTransmog(){
|
||||||
|
this.removeElement(this.innerScreen);
|
||||||
|
this.modifierCategory = ModifierCategory.NORMAL;
|
||||||
|
updateModifierCategoryButtonLabel();
|
||||||
|
ISpatial modListSpatial = Spatials.positionXY(7, 50).size(this.getGuiSpatial().width() - 14, this.getGuiSpatial().height() - 57);
|
||||||
|
this.innerScreen = new TransmogListContainer(modListSpatial, getCurrGear()).layout(this.translateWorldSpatial());
|
||||||
|
this.disableCategoryButtons();
|
||||||
|
this.disableLvlButtons();
|
||||||
|
this.windowNameLabel.set(new TranslatableComponent("vhatcaniroll.screen.title.transmogs").withStyle(ChatFormatting.BLACK));
|
||||||
|
this.addElement(this.innerScreen);
|
||||||
|
ScreenLayout.requestLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void switchToModifiers(){
|
||||||
|
this.removeElement(this.innerScreen);
|
||||||
|
ISpatial modListSpatial = Spatials.positionXY(7, 50).size(this.getGuiSpatial().width() - 14, this.getGuiSpatial().height() - 57);
|
||||||
|
this.innerScreen = new ModifierListContainer(modListSpatial, lvlInput.getValue(), modifierCategory, getCurrGear()).layout(this.translateWorldSpatial());
|
||||||
|
this.enableCategoryButtons();
|
||||||
|
this.enableLvlButtons();
|
||||||
|
this.windowNameLabel.set(new TranslatableComponent("vhatcaniroll.screen.title.random").withStyle(ChatFormatting.BLACK));
|
||||||
|
this.addElement(this.innerScreen);
|
||||||
|
ScreenLayout.requestLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void switchToCrafted(){
|
||||||
|
this.removeElement(this.innerScreen);
|
||||||
|
this.modifierCategory = ModifierCategory.NORMAL;
|
||||||
|
updateModifierCategoryButtonLabel();
|
||||||
|
ISpatial modListSpatial = Spatials.positionXY(7, 50).size(this.getGuiSpatial().width() - 14, this.getGuiSpatial().height() - 57);
|
||||||
|
this.innerScreen = new CraftedModifiersListContainer(modListSpatial, lvlInput.getValue(), modifierCategory, getCurrGear()).layout(this.translateWorldSpatial());
|
||||||
|
this.enableLvlButtons();
|
||||||
|
this.disableCategoryButtons();
|
||||||
|
this.windowNameLabel.set(new TranslatableComponent("vhatcaniroll.screen.title.crafted").withStyle(ChatFormatting.BLACK));
|
||||||
|
this.addElement(this.innerScreen);
|
||||||
|
ScreenLayout.requestLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void switchToUnique(){
|
||||||
|
this.removeElement(this.innerScreen);
|
||||||
|
this.modifierCategory = ModifierCategory.NORMAL;
|
||||||
|
updateModifierCategoryButtonLabel();
|
||||||
|
ISpatial modListSpatial = Spatials.positionXY(7, 50).size(this.getGuiSpatial().width() - 14, this.getGuiSpatial().height() - 57);
|
||||||
|
this.innerScreen = new UniqueGearListContainer(modListSpatial, lvlInput.getValue(), modifierCategory, getCurrGear()).layout(this.translateWorldSpatial());
|
||||||
|
this.enableLvlButtons();
|
||||||
|
this.disableCategoryButtons();
|
||||||
|
this.windowNameLabel.set(new TranslatableComponent("vhatcaniroll.screen.title.unique").withStyle(ChatFormatting.BLACK));
|
||||||
|
this.addElement(this.innerScreen);
|
||||||
|
ScreenLayout.requestLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private void enableCategoryButtons(){
|
||||||
|
this.modifierCategoryLabel.setVisible(true);
|
||||||
|
this.modifierCategoryButton.setVisible(true);
|
||||||
|
this.modifierCategoryButton.setDisabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void disableCategoryButtons(){
|
||||||
|
this.modifierCategoryLabel.setVisible(false);
|
||||||
|
this.modifierCategoryButton.setVisible(false);
|
||||||
|
this.modifierCategoryButton.setDisabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void enableLvlButtons(){
|
||||||
|
this.lvlInput.setVisible(true);
|
||||||
|
this.minusButton.setVisible(true);
|
||||||
|
this.minusLabel.setVisible(true);
|
||||||
|
this.plusButton.setVisible(true);
|
||||||
|
this.plusLabel.setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void disableLvlButtons(){
|
||||||
|
this.lvlInput.setVisible(false);
|
||||||
|
this.minusButton.setVisible(false);
|
||||||
|
this.minusLabel.setVisible(false);
|
||||||
|
this.plusButton.setVisible(false);
|
||||||
|
this.plusLabel.setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// pulled from QuestOverviewElementScreen
|
||||||
|
private ILayoutStrategy translateWorldSpatial() {
|
||||||
|
return (screen, gui, parent, world) -> world.translateXY(this.getGuiSpatial());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 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));
|
||||||
|
}
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
return Spatials.positionXY(342, 40 + (tabIndex-11) * 30);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private TabElement<?> getTabElement(int tabIndex, boolean 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<>(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))
|
||||||
|
.layout(this.translateWorldSpatial());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void switchTab(int tabIndex) {
|
||||||
|
for (int i = 0; i < Items.getVaultGearItems().size(); i++) {
|
||||||
|
this.removeElement(tabs.get(i));
|
||||||
|
TabElement<?> tab = getTabElement(i, i == tabIndex);
|
||||||
|
tabs.set(i, tab);
|
||||||
|
this.addElement(tab);
|
||||||
|
}
|
||||||
|
this.currIndex = tabIndex;
|
||||||
|
updateModifierList(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
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(this.translateWorldSpatial())
|
||||||
|
);
|
||||||
|
inputElement.onTextChanged(s -> updateModifierList(true));
|
||||||
|
return inputElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createLvlButtons(ScrollableLvlInputElement lvlInput) {
|
||||||
|
LabelElement<?> minusLabel =
|
||||||
|
new LabelElement<>(Spatials.positionXY(this.getGuiSpatial().width() - 68 - 13, 38), new TextComponent("-"),
|
||||||
|
LabelTextStyle.border4(ChatFormatting.BLACK))
|
||||||
|
.layout(this.translateWorldSpatial());
|
||||||
|
LabelElement<?> plusLabel =
|
||||||
|
new LabelElement<>(Spatials.positionXY(this.getGuiSpatial().width() - 21 - 13, 38), new TextComponent("+"),
|
||||||
|
LabelTextStyle.border4(ChatFormatting.BLACK))
|
||||||
|
.layout(this.translateWorldSpatial());
|
||||||
|
NineSliceButtonElement<?> btnMinus =
|
||||||
|
new NineSliceButtonElement<>(Spatials.positionXY(this.getGuiSpatial().width() - 72 - 13, 35).size(15, 14),
|
||||||
|
ScreenTextures.BUTTON_EMPTY_TEXTURES, lvlInput::decrement).layout(this.translateWorldSpatial());
|
||||||
|
NineSliceButtonElement<?> btnPlus =
|
||||||
|
new NineSliceButtonElement<>(Spatials.positionXY(this.getGuiSpatial().width() - 25 - 13, 35).size(15, 14),
|
||||||
|
ScreenTextures.BUTTON_EMPTY_TEXTURES, lvlInput::increment).layout(this.translateWorldSpatial());
|
||||||
|
this.minusButton = this.addElement(btnMinus);
|
||||||
|
this.minusLabel = this.addElement(minusLabel);
|
||||||
|
this.plusLabel = this.addElement(plusLabel);
|
||||||
|
this.plusButton = this.addElement(btnPlus);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void nextModifierCategory() {
|
||||||
|
if (!(this.innerScreen instanceof ModifierListContainer)) return;
|
||||||
|
this.modifierCategory = modifierCategory.next();
|
||||||
|
updateModifierCategoryButtonLabel();
|
||||||
|
updateModifierList(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void previousModifierCategory() {
|
||||||
|
if (!(this.innerScreen instanceof ModifierListContainer)) return;
|
||||||
|
this.modifierCategory = modifierCategory.previous();
|
||||||
|
updateModifierCategoryButtonLabel();
|
||||||
|
updateModifierList(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateModifierCategoryButtonLabel() {
|
||||||
|
if (this.modifierCategoryLabel != null) {
|
||||||
|
this.removeElement(this.modifierCategoryLabel);
|
||||||
|
}
|
||||||
|
this.modifierCategoryLabel = new LabelElement<>(Spatials.positionXY(this.getGuiSpatial().width() - 5 - 13, 38),
|
||||||
|
new TextComponent(modifierCategory.getSymbol()).withStyle(modifierCategory.getStyle()), LabelTextStyle.defaultStyle())
|
||||||
|
.layout(this.translateWorldSpatial());
|
||||||
|
this.addElement(modifierCategoryLabel);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createModifierCategoryButton() {
|
||||||
|
updateModifierCategoryButtonLabel();
|
||||||
|
NineSliceButtonElement<?> btnLegend =
|
||||||
|
new NineSliceButtonElement<>(Spatials.positionXY(this.getGuiSpatial().width() - 8 - 13, 35).size(14, 14),
|
||||||
|
ScreenTextures.BUTTON_EMPTY_TEXTURES, () -> {
|
||||||
|
if (hasShiftDown()) {
|
||||||
|
previousModifierCategory();
|
||||||
|
} else {
|
||||||
|
nextModifierCategory();
|
||||||
|
}
|
||||||
|
}).layout(this.translateWorldSpatial());
|
||||||
|
this.addElement(btnLegend);
|
||||||
|
this.modifierCategoryButton = btnLegend;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createConfigButton(){
|
||||||
|
this.addElement(new ButtonElement<>(Spatials.positionXY(-3, 3), ScreenTextures.BUTTON_HISTORY_TEXTURES, () -> {
|
||||||
|
SubMenuConfigScreen screen = new SubMenuConfigScreen(this, "VHat Can I Roll? Configuration", ModConfig.Type.CLIENT, Config.SPEC, Config.SPEC.getValues());
|
||||||
|
ConfigScreen.modID = VHatCanIRoll.MODID;
|
||||||
|
Minecraft.getInstance().setScreen(screen);
|
||||||
|
|
||||||
|
})).layout((screen, gui, parent, world) -> {
|
||||||
|
world.width(21).height(21).translateX(gui.left() - 18).translateY(this.getGuiSpatial().bottom() - 26);
|
||||||
|
}).tooltip(
|
||||||
|
Tooltips.single(TooltipDirection.LEFT,() -> new TextComponent("Configuration"))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createHelpButton(HelpContainer hc) {
|
||||||
|
this.addElement(new ButtonElement<>(Spatials.positionXY(-3, 3), ScreenTextures.BUTTON_QUEST_TEXTURES, () -> {
|
||||||
|
hc.setVisible(!hc.isVisible());
|
||||||
|
})).layout((screen, gui, parent, world) -> {
|
||||||
|
world.width(21).height(21).translateX(gui.left() - 18).translateY(this.getGuiSpatial().bottom() - 48);
|
||||||
|
}).tooltip(
|
||||||
|
Tooltips.single(TooltipDirection.LEFT, () -> new TextComponent("Help"))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createModifierButton() {
|
||||||
|
this.addElement(new ButtonElement<>(Spatials.positionXY(-3, 3), ScreenTextures.BUTTON_EMPTY_16_TEXTURES, () -> {
|
||||||
|
if (!(this.innerScreen instanceof ModifierListContainer))
|
||||||
|
switchToModifiers();
|
||||||
|
})).layout((screen, gui, parent, world) -> {
|
||||||
|
world.width(21).height(21).translateX(gui.left() - 16).translateY(this.getGuiSpatial().top() + 50);
|
||||||
|
}).tooltip(
|
||||||
|
Tooltips.single(TooltipDirection.LEFT, () -> new TranslatableComponent("vhatcaniroll.screen.title.random"))
|
||||||
|
);
|
||||||
|
|
||||||
|
ItemStack chestplateStack = new ItemStack(ModItems.CHESTPLATE);
|
||||||
|
this.addElement(
|
||||||
|
new FakeItemSlotElement<>(Spatials.positionXY(-3, 3), () -> chestplateStack, () -> false, ScreenTextures.EMPTY, ScreenTextures.EMPTY)
|
||||||
|
.layout((screen, gui, parent, world) -> world.width(21).height(21).translateX(gui.left() - 16).translateY(this.getGuiSpatial().top() + 50))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createUniqueGearButton() {
|
||||||
|
this.addElement(new ButtonElement<>(Spatials.positionXY(-3, 3), ScreenTextures.BUTTON_EMPTY_16_TEXTURES, () -> {
|
||||||
|
if (!(this.innerScreen instanceof UniqueGearListContainer))
|
||||||
|
switchToUnique();
|
||||||
|
})).layout((screen, gui, parent, world) -> {
|
||||||
|
world.width(21).height(21).translateX(gui.left() - 16).translateY(this.getGuiSpatial().top() + 70);
|
||||||
|
}).tooltip(
|
||||||
|
Tooltips.single(TooltipDirection.LEFT, () -> new TranslatableComponent("vhatcaniroll.screen.title.unique"))
|
||||||
|
);
|
||||||
|
ItemStack chestplateStack = new ItemStack(ModItems.CHESTPLATE);
|
||||||
|
VaultGearData gearData = VaultGearData.read(chestplateStack);
|
||||||
|
gearData.createOrReplaceAttributeValue(ModGearAttributes.GEAR_ROLL_TYPE, "Unique");
|
||||||
|
gearData.write(chestplateStack);
|
||||||
|
this.addElement(
|
||||||
|
new FakeItemSlotElement<>(Spatials.positionXY(-3, 3), () -> chestplateStack, () -> false, ScreenTextures.EMPTY, ScreenTextures.EMPTY)
|
||||||
|
.layout((screen, gui, parent, world) -> world.width(21).height(21).translateX(gui.left() - 16).translateY(this.getGuiSpatial().top() + 70))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createTransmogButton() {
|
||||||
|
this.addElement(new ButtonElement<>(Spatials.positionXY(-3, 3), ScreenTextures.BUTTON_EMPTY_16_TEXTURES, () -> {
|
||||||
|
if (!(this.innerScreen instanceof TransmogListContainer))
|
||||||
|
switchToTransmog();
|
||||||
|
})).layout((screen, gui, parent, world) -> {
|
||||||
|
world.width(21).height(21).translateX(gui.left() - 16).translateY(this.getGuiSpatial().top() + 90);
|
||||||
|
}).tooltip(
|
||||||
|
Tooltips.single(TooltipDirection.LEFT, () -> new TranslatableComponent("vhatcaniroll.screen.title.transmogs"))
|
||||||
|
);
|
||||||
|
ItemStack chestplateStack = new ItemStack(ModItems.CHESTPLATE);
|
||||||
|
VaultGearData gearData = VaultGearData.read(chestplateStack);
|
||||||
|
gearData.setState(VaultGearState.IDENTIFIED);
|
||||||
|
gearData.createOrReplaceAttributeValue(ModGearAttributes.GEAR_MODEL, new ResourceLocation("the_vault:gear/armor/flamingo/chestplate"));
|
||||||
|
gearData.write(chestplateStack);
|
||||||
|
this.addElement(
|
||||||
|
new FakeItemSlotElement<>(Spatials.positionXY(-3, 3), () -> chestplateStack, () -> false, ScreenTextures.EMPTY, ScreenTextures.EMPTY)
|
||||||
|
.layout((screen, gui, parent, world) -> world.width(21).height(21).translateX(gui.left() - 16).translateY(this.getGuiSpatial().top() + 90))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createCraftedModsButton() {
|
||||||
|
this.addElement(new ButtonElement<>(Spatials.positionXY(-3, 3), ScreenTextures.BUTTON_EMPTY_16_TEXTURES, () -> {
|
||||||
|
if (!(this.innerScreen instanceof CraftedModifiersListContainer))
|
||||||
|
switchToCrafted();
|
||||||
|
})).layout((screen, gui, parent, world) -> {
|
||||||
|
world.width(21).height(21).translateX(gui.left() - 16).translateY(this.getGuiSpatial().top() + 110);
|
||||||
|
}).tooltip(
|
||||||
|
Tooltips.single(TooltipDirection.LEFT, () -> new TranslatableComponent("vhatcaniroll.screen.title.crafted"))
|
||||||
|
);
|
||||||
|
ItemStack workbenchStack = new ItemStack(ModBlocks.MODIFIER_WORKBENCH);
|
||||||
|
this.addElement(
|
||||||
|
new FakeItemSlotElement<>(Spatials.positionXY(-3, 3), () -> workbenchStack, () -> false, ScreenTextures.EMPTY, ScreenTextures.EMPTY)
|
||||||
|
.layout((screen, gui, parent, world) -> world.width(21).height(21).translateX(gui.left() - 16).translateY(this.getGuiSpatial().top() + 110))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@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) {
|
||||||
|
lvlInput.increment();
|
||||||
|
}
|
||||||
|
if (keyCode == InputConstants.KEY_H || keyCode == InputConstants.KEY_LEFT) {
|
||||||
|
lvlInput.decrement();
|
||||||
|
}
|
||||||
|
// up/down to scroll up/down
|
||||||
|
if (keyCode == InputConstants.KEY_K || keyCode == InputConstants.KEY_UP) {
|
||||||
|
if (this.innerScreen instanceof VerticalScrollClipContainer<?> vsc){
|
||||||
|
vsc.onMouseScrolled(0,0,1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (keyCode == InputConstants.KEY_J || keyCode == InputConstants.KEY_DOWN) {
|
||||||
|
if (this.innerScreen instanceof VerticalScrollClipContainer<?> vsc){
|
||||||
|
vsc.onMouseScrolled(0,0,-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// tab to next gear item
|
||||||
|
if (keyCode == InputConstants.KEY_TAB && !hasShiftDown()) {
|
||||||
|
switchTab((currIndex + 1) % Items.getVaultGearItems().size());
|
||||||
|
}
|
||||||
|
// shift+tab to previous gear item
|
||||||
|
if (keyCode == InputConstants.KEY_TAB && hasShiftDown()) {
|
||||||
|
switchTab((currIndex - 1 + Items.getVaultGearItems().size()) % Items.getVaultGearItems().size());
|
||||||
|
}
|
||||||
|
// ctrl to change modifier category (normal, greater, legendary)
|
||||||
|
if (keyCode == InputConstants.KEY_LCONTROL || keyCode == InputConstants.KEY_RCONTROL) {
|
||||||
|
if (hasShiftDown()) {
|
||||||
|
previousModifierCategory();
|
||||||
|
} else {
|
||||||
|
nextModifierCategory();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.keyPressed(keyCode, scanCode, modifiers);
|
||||||
|
}
|
||||||
|
}
|
||||||
119
src/main/java/com/radimous/vhatcaniroll/ui/HelpContainer.java
Normal file
119
src/main/java/com/radimous/vhatcaniroll/ui/HelpContainer.java
Normal file
|
|
@ -0,0 +1,119 @@
|
||||||
|
package com.radimous.vhatcaniroll.ui;
|
||||||
|
|
||||||
|
import com.radimous.vhatcaniroll.logic.ModifierCategory;
|
||||||
|
import iskallia.vault.client.gui.framework.element.ContainerElement;
|
||||||
|
import iskallia.vault.client.gui.framework.element.LabelElement;
|
||||||
|
import iskallia.vault.client.gui.framework.element.spi.ILayoutStrategy;
|
||||||
|
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 net.minecraft.ChatFormatting;
|
||||||
|
import net.minecraft.network.chat.TextComponent;
|
||||||
|
|
||||||
|
public class HelpContainer extends ContainerElement<HelpContainer> {
|
||||||
|
public HelpContainer(ISpatial spatial) {
|
||||||
|
super(spatial);
|
||||||
|
this.setVisible(false); // Hide by default
|
||||||
|
|
||||||
|
LabelElement<?> tabLabel = new LabelElement<>(
|
||||||
|
Spatials.positionXY(336, 16).width(16).height(16),
|
||||||
|
new TextComponent("TAB").withStyle(ChatFormatting.GOLD),
|
||||||
|
LabelTextStyle.shadow()
|
||||||
|
).layout(this.translateWorldSpatial());
|
||||||
|
this.addElement(tabLabel);
|
||||||
|
|
||||||
|
LabelElement<?> shiftTabLabel = new LabelElement<>(
|
||||||
|
Spatials.positionXY(-60, 16).width(16).height(16),
|
||||||
|
new TextComponent("SHIFT + TAB").withStyle(ChatFormatting.GOLD),
|
||||||
|
LabelTextStyle.shadow()
|
||||||
|
).layout(this.translateWorldSpatial());
|
||||||
|
this.addElement(shiftTabLabel);
|
||||||
|
|
||||||
|
LabelElement<?> arrows = new LabelElement<>(
|
||||||
|
Spatials.positionXY(260, 54).width(16).height(16),
|
||||||
|
new TextComponent("← ").withStyle(ChatFormatting.GOLD)
|
||||||
|
.append(new TextComponent("scroll").withStyle(ChatFormatting.BLUE))
|
||||||
|
.append(new TextComponent(" →").withStyle(ChatFormatting.GOLD)),
|
||||||
|
LabelTextStyle.shadow()
|
||||||
|
).layout(this.translateWorldSpatial());
|
||||||
|
this.addElement(arrows);
|
||||||
|
|
||||||
|
LabelElement<?> vimArrows = new LabelElement<>(
|
||||||
|
Spatials.positionXY(262, 64).width(16).height(16),
|
||||||
|
new TextComponent("h ").withStyle(ChatFormatting.GOLD)
|
||||||
|
.append(new TextComponent("wheel").withStyle(ChatFormatting.BLUE))
|
||||||
|
.append(new TextComponent(" l").withStyle(ChatFormatting.GOLD)),
|
||||||
|
LabelTextStyle.shadow()
|
||||||
|
).layout(this.translateWorldSpatial());
|
||||||
|
this.addElement(vimArrows);
|
||||||
|
|
||||||
|
LabelElement<?> ctrlLabel = new LabelElement<>(
|
||||||
|
Spatials.positionXY(365, 38).width(16).height(16),
|
||||||
|
new TextComponent("CTRL").withStyle(ChatFormatting.GOLD),
|
||||||
|
LabelTextStyle.shadow()
|
||||||
|
).layout(this.translateWorldSpatial());
|
||||||
|
this.addElement(ctrlLabel);
|
||||||
|
|
||||||
|
LabelElement<?> categoryLabelNormal = new LabelElement<>(
|
||||||
|
Spatials.positionXY(375, 52).width(16).height(16),
|
||||||
|
new TextComponent(ModifierCategory.NORMAL.name()).withStyle(ModifierCategory.NORMAL.getStyle()),
|
||||||
|
LabelTextStyle.shadow()
|
||||||
|
).layout(this.translateWorldSpatial());
|
||||||
|
this.addElement(categoryLabelNormal);
|
||||||
|
|
||||||
|
LabelElement<?> categoryLabelGreater = new LabelElement<>(
|
||||||
|
Spatials.positionXY(375, 62).width(16).height(16),
|
||||||
|
new TextComponent(ModifierCategory.GREATER.name()).withStyle(ModifierCategory.GREATER.getStyle()),
|
||||||
|
LabelTextStyle.shadow()
|
||||||
|
).layout(this.translateWorldSpatial());
|
||||||
|
this.addElement(categoryLabelGreater);
|
||||||
|
|
||||||
|
LabelElement<?> categoryLabelLegendary = new LabelElement<>(
|
||||||
|
Spatials.positionXY(375, 72).width(16).height(16),
|
||||||
|
new TextComponent(ModifierCategory.LEGENDARY.name()).withStyle(ModifierCategory.LEGENDARY.getStyle()),
|
||||||
|
LabelTextStyle.shadow()
|
||||||
|
).layout(this.translateWorldSpatial());
|
||||||
|
this.addElement(categoryLabelLegendary);
|
||||||
|
|
||||||
|
LabelElement<?> upLabel = new LabelElement<>(
|
||||||
|
Spatials.positionXY(340, 190).width(16).height(16),
|
||||||
|
new TextComponent("↑ k").withStyle(ChatFormatting.GOLD),
|
||||||
|
LabelTextStyle.shadow()
|
||||||
|
).layout(this.translateWorldSpatial());
|
||||||
|
this.addElement(upLabel);
|
||||||
|
LabelElement<?> downLabel = new LabelElement<>(
|
||||||
|
Spatials.positionXY(340, 204).width(16).height(16),
|
||||||
|
new TextComponent("↓ j").withStyle(ChatFormatting.GOLD),
|
||||||
|
LabelTextStyle.shadow()
|
||||||
|
).layout(this.translateWorldSpatial());
|
||||||
|
this.addElement(downLabel);
|
||||||
|
|
||||||
|
|
||||||
|
String text = """
|
||||||
|
Colored triangles
|
||||||
|
represent groups
|
||||||
|
of modifiers.
|
||||||
|
|
||||||
|
If 2 modifiers are
|
||||||
|
in the same group,
|
||||||
|
they can't be
|
||||||
|
rolled together.
|
||||||
|
""";
|
||||||
|
|
||||||
|
String[] array = text.split("\n");
|
||||||
|
int labelY = 120;
|
||||||
|
for (String s : array) {
|
||||||
|
LabelElement<?> textLabel = new LabelElement<>(
|
||||||
|
Spatials.positionXY(-100, labelY).width(20).height(15),
|
||||||
|
new TextComponent(s).withStyle(ChatFormatting.GOLD), LabelTextStyle.shadow()
|
||||||
|
).layout(this.translateWorldSpatial());
|
||||||
|
this.addElement(textLabel);
|
||||||
|
labelY += 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
private ILayoutStrategy translateWorldSpatial() {
|
||||||
|
return (screen, gui, parent, world) -> world.translateXY(gui);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
package com.radimous.vhatcaniroll.ui;
|
||||||
|
|
||||||
|
import com.radimous.vhatcaniroll.logic.ModifierCategory;
|
||||||
|
import iskallia.vault.client.gui.framework.element.spi.IElement;
|
||||||
|
import iskallia.vault.client.gui.framework.spatial.spi.ISpatial;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
|
||||||
|
public interface InnerGearScreen extends IElement {
|
||||||
|
float getScroll();
|
||||||
|
void setScroll(float scroll);
|
||||||
|
InnerGearScreen create(ISpatial spatial, int lvl, ModifierCategory modifierCategory, ItemStack gearPiece);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
package com.radimous.vhatcaniroll.ui;
|
||||||
|
|
||||||
|
import com.radimous.vhatcaniroll.logic.ModifierCategory;
|
||||||
|
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.Component;
|
||||||
|
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<ModifierListContainer> implements InnerGearScreen {
|
||||||
|
|
||||||
|
public ModifierListContainer(ISpatial spatial, int lvl, ModifierCategory modifierCategory, ItemStack gearPiece) {
|
||||||
|
super(spatial, Padding.ZERO, ScreenTextures.INSET_BLACK_BACKGROUND);
|
||||||
|
int labelX = 9;
|
||||||
|
int labelY = 20;
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
.withStyle(ChatFormatting.UNDERLINE).withStyle(modifierCategory.getStyle()), LabelTextStyle.defaultStyle()
|
||||||
|
);
|
||||||
|
this.addElement(itemName);
|
||||||
|
|
||||||
|
Optional<VaultGearTierConfig> optCfg = VaultGearTierConfig.getConfig(gearPiece);
|
||||||
|
if (optCfg.isPresent()) {
|
||||||
|
VaultGearTierConfig cfg = optCfg.get();
|
||||||
|
for (Component modifier : Modifiers.getModifierList(lvl, cfg, modifierCategory)) {
|
||||||
|
LabelElement<?> labelelement = new LabelElement<>(
|
||||||
|
Spatials.positionXY(labelX, labelY).width(this.innerWidth() - labelX).height(15), modifier, LabelTextStyle.defaultStyle()
|
||||||
|
);
|
||||||
|
/* TODO: display individual modifier tiers
|
||||||
|
I want to display
|
||||||
|
<groupPrefix> <value> <name> <chance>
|
||||||
|
and make it expandable to show all tiers of the modifier
|
||||||
|
|
||||||
|
<groupPrefix> <value> <name> <chance>
|
||||||
|
<groupPrefix> <value> <name> <chance>
|
||||||
|
<groupPrefix> <value> <name> <chance>
|
||||||
|
<groupPrefix> <value> <name> <chance>
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InnerGearScreen create(ISpatial spatial, int lvl, ModifierCategory modifierCategory, ItemStack gearPiece) {
|
||||||
|
return new ModifierListContainer(spatial, lvl, modifierCategory, gearPiece);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,88 @@
|
||||||
|
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<ScrollableLvlInputElement> {
|
||||||
|
public ScrollableLvlInputElement(ISpatial spatial, Font font) {
|
||||||
|
super(spatial, font);
|
||||||
|
this.adjustEditBox(editBox -> {
|
||||||
|
editBox.setFilter(s -> isValidLevel(parseInt(s)));
|
||||||
|
editBox.setMaxLength(3);
|
||||||
|
editBox.setValue(String.valueOf(VaultBarOverlay.vaultLevel));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@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);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public boolean onMouseClicked(double mouseX, double mouseY, int buttonIndex) {
|
||||||
|
if (buttonIndex == 1) { // right
|
||||||
|
this.setInput("");
|
||||||
|
}
|
||||||
|
if (buttonIndex == 2){ // middle
|
||||||
|
this.setValue(VaultBarOverlay.vaultLevel);
|
||||||
|
}
|
||||||
|
return super.onMouseClicked(mouseX, mouseY, buttonIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public boolean charTyped(char charTyped, int keyCode) {
|
||||||
|
if (!Character.isDigit(charTyped)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return super.charTyped(charTyped, keyCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,93 @@
|
||||||
|
package com.radimous.vhatcaniroll.ui;
|
||||||
|
|
||||||
|
import com.radimous.vhatcaniroll.logic.ModifierCategory;
|
||||||
|
import iskallia.vault.block.TransmogTableBlock;
|
||||||
|
import iskallia.vault.client.ClientDiscoveredEntriesData;
|
||||||
|
import iskallia.vault.client.gui.framework.ScreenTextures;
|
||||||
|
import iskallia.vault.client.gui.framework.element.DiscoveredModelSelectElement;
|
||||||
|
import iskallia.vault.client.gui.framework.element.FakeItemSlotElement;
|
||||||
|
import iskallia.vault.client.gui.framework.element.LabelElement;
|
||||||
|
import iskallia.vault.client.gui.framework.element.NineSliceButtonElement;
|
||||||
|
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.gear.VaultGearRarity;
|
||||||
|
import iskallia.vault.gear.VaultGearState;
|
||||||
|
import iskallia.vault.gear.data.VaultGearData;
|
||||||
|
import iskallia.vault.init.ModConfigs;
|
||||||
|
import iskallia.vault.init.ModDynamicModels;
|
||||||
|
import iskallia.vault.init.ModGearAttributes;
|
||||||
|
import iskallia.vault.util.SideOnlyFixer;
|
||||||
|
import iskallia.vault.util.function.ObservableSupplier;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.player.LocalPlayer;
|
||||||
|
import net.minecraft.network.chat.Style;
|
||||||
|
import net.minecraft.network.chat.TextComponent;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import static iskallia.vault.client.gui.framework.ScreenTextures.BUTTON_EMPTY;
|
||||||
|
import static iskallia.vault.client.gui.framework.ScreenTextures.BUTTON_EMPTY_DISABLED;
|
||||||
|
|
||||||
|
public class TransmogListContainer extends VerticalScrollClipContainer<TransmogListContainer> implements InnerGearScreen {
|
||||||
|
|
||||||
|
public TransmogListContainer(ISpatial spatial, ItemStack gearPiece) {
|
||||||
|
super(spatial, Padding.ZERO, ScreenTextures.INSET_BLACK_BACKGROUND);
|
||||||
|
int labelX = 9;
|
||||||
|
int labelY = 0;
|
||||||
|
|
||||||
|
LocalPlayer player = Minecraft.getInstance().player;
|
||||||
|
if (player == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Set<ResourceLocation> discoveredModelIds = ClientDiscoveredEntriesData.Models.getDiscoveredModels();
|
||||||
|
ObservableSupplier<Set<ResourceLocation>> discoveredModelObserverIds = ClientDiscoveredEntriesData.Models.getObserverModels();
|
||||||
|
DiscoveredModelSelectElement.DiscoveredModelSelectorModel model = new DiscoveredModelSelectElement.DiscoveredModelSelectorModel(
|
||||||
|
ObservableSupplier.of(() -> gearPiece, SideOnlyFixer::stackEqualExact), discoveredModelObserverIds, x -> {});
|
||||||
|
List<DiscoveredModelSelectElement.TransmogModelEntry> mEntries = model.getEntries();
|
||||||
|
for (DiscoveredModelSelectElement.TransmogModelEntry x : mEntries) {
|
||||||
|
ItemStack displayStack = new ItemStack(gearPiece.getItem());
|
||||||
|
VaultGearData gearData = VaultGearData.read(displayStack);
|
||||||
|
gearData.setState(VaultGearState.IDENTIFIED);
|
||||||
|
gearData.createOrReplaceAttributeValue(ModGearAttributes.GEAR_MODEL, x.getModelId());
|
||||||
|
gearData.write(displayStack);
|
||||||
|
this.addElement(new FakeItemSlotElement<>(Spatials.positionXY(labelX, labelY).width(16).height(16), () -> displayStack, () -> false, ScreenTextures.EMPTY, ScreenTextures.EMPTY));
|
||||||
|
var oMod = ModDynamicModels.REGISTRIES.getModel(gearPiece.getItem(), x.getModelId());
|
||||||
|
if (oMod.isPresent()) {
|
||||||
|
var mod = oMod.get();
|
||||||
|
VaultGearRarity rollRarity = ModConfigs.GEAR_MODEL_ROLL_RARITIES.getRarityOf(gearPiece, mod.getId());
|
||||||
|
this.addElement(new LabelElement<>(
|
||||||
|
Spatials.positionXY(labelX + 20, labelY + 6).width(this.innerWidth() - labelX).height(15),
|
||||||
|
new TextComponent(mod.getDisplayName()).withStyle(Style.EMPTY.withColor(rollRarity.getColor().getValue())), LabelTextStyle.defaultStyle()));
|
||||||
|
|
||||||
|
NineSliceButtonElement<?> btn = new NineSliceButtonElement<>(Spatials.positionXY(0, labelY ).width(innerWidth()).height(18),
|
||||||
|
new NineSliceButtonElement.NineSliceButtonTextures(BUTTON_EMPTY, BUTTON_EMPTY, BUTTON_EMPTY, BUTTON_EMPTY_DISABLED), () -> {});
|
||||||
|
boolean canTransmog = TransmogTableBlock.canTransmogModel(player, discoveredModelIds, x.getModelId());
|
||||||
|
btn.setDisabled(!canTransmog);
|
||||||
|
this.addElement(btn);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
labelY += 18;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public float getScroll() {
|
||||||
|
return this.verticalScrollBarElement.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setScroll(float scroll) {
|
||||||
|
this.verticalScrollBarElement.setValue(scroll);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InnerGearScreen create(ISpatial spatial, int lvl, ModifierCategory modifierCategory, ItemStack gearPiece) {
|
||||||
|
return new TransmogListContainer(spatial, gearPiece);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,136 @@
|
||||||
|
package com.radimous.vhatcaniroll.ui;
|
||||||
|
|
||||||
|
import com.radimous.vhatcaniroll.Config;
|
||||||
|
import com.radimous.vhatcaniroll.logic.ModifierCategory;
|
||||||
|
import com.radimous.vhatcaniroll.logic.Modifiers;
|
||||||
|
import com.radimous.vhatcaniroll.mixin.UniqueGearConfigAccessor;
|
||||||
|
import com.radimous.vhatcaniroll.mixin.VaultGearTierConfigAccessor;
|
||||||
|
import iskallia.vault.client.gui.framework.ScreenTextures;
|
||||||
|
import iskallia.vault.client.gui.framework.element.FakeItemSlotElement;
|
||||||
|
import iskallia.vault.client.gui.framework.element.LabelElement;
|
||||||
|
import iskallia.vault.client.gui.framework.element.NineSliceElement;
|
||||||
|
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.UniqueGearConfig;
|
||||||
|
import iskallia.vault.config.gear.VaultGearTierConfig;
|
||||||
|
import iskallia.vault.gear.VaultGearState;
|
||||||
|
import iskallia.vault.gear.data.VaultGearData;
|
||||||
|
import iskallia.vault.init.ModConfigs;
|
||||||
|
import iskallia.vault.init.ModGearAttributes;
|
||||||
|
import net.minecraft.ChatFormatting;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.network.chat.TextComponent;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class UniqueGearListContainer extends VerticalScrollClipContainer<UniqueGearListContainer> implements InnerGearScreen {
|
||||||
|
|
||||||
|
public UniqueGearListContainer(ISpatial spatial, int lvl, ModifierCategory modifierCategory, ItemStack gearPiece) {
|
||||||
|
super(spatial, Padding.ZERO, ScreenTextures.INSET_BLACK_BACKGROUND);
|
||||||
|
int labelX = 9;
|
||||||
|
int labelY = 9;
|
||||||
|
|
||||||
|
Map<ResourceLocation, UniqueGearConfig.Entry> uniqueRegistry = ((UniqueGearConfigAccessor) ModConfigs.UNIQUE_GEAR).getRegistry();
|
||||||
|
ResourceLocation regName = gearPiece.getItem().getRegistryName();
|
||||||
|
if (regName == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String regPath = regName.getPath();
|
||||||
|
|
||||||
|
var goodEntries = uniqueRegistry.entrySet().stream().filter(entry -> entry.getValue().getModel() != null && entry.getValue().getModel().toString().contains(regPath)).toList();
|
||||||
|
|
||||||
|
|
||||||
|
VaultGearTierConfigAccessor uniqueConfig1 = (VaultGearTierConfigAccessor) ModConfigs.VAULT_GEAR_CONFIG.get(VaultGearTierConfig.UNIQUE_ITEM);
|
||||||
|
if (uniqueConfig1 == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (Map.Entry<ResourceLocation, UniqueGearConfig.Entry> entry : goodEntries) {
|
||||||
|
UniqueGearConfig.Entry value = entry.getValue();
|
||||||
|
String name = value.getName();
|
||||||
|
if (name == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ResourceLocation model = value.getModel();
|
||||||
|
if (model == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<UniqueGearConfig.AffixTargetType, List<ResourceLocation>> modifierIdentifiers = value.getModifierIdentifiers();
|
||||||
|
if (modifierIdentifiers == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int iconHeight = labelY;
|
||||||
|
|
||||||
|
labelY += 5;
|
||||||
|
LabelElement<?> nameLabel = new LabelElement<>(
|
||||||
|
Spatials.positionXY(labelX + 20, labelY).width(this.innerWidth() - labelX).height(15),
|
||||||
|
new TextComponent(name), LabelTextStyle.defaultStyle()
|
||||||
|
);
|
||||||
|
this.addElement(nameLabel);
|
||||||
|
labelY += 20;
|
||||||
|
|
||||||
|
ItemStack displayStack = new ItemStack(gearPiece.getItem());
|
||||||
|
VaultGearData gearData = VaultGearData.read(displayStack);
|
||||||
|
gearData.setState(VaultGearState.IDENTIFIED);
|
||||||
|
gearData.createOrReplaceAttributeValue(ModGearAttributes.GEAR_MODEL, model);
|
||||||
|
gearData.write(displayStack);
|
||||||
|
this.addElement(new FakeItemSlotElement<>(Spatials.positionXY(labelX - 4, iconHeight).width(16).height(16), () -> displayStack, () -> false, ScreenTextures.EMPTY, ScreenTextures.EMPTY));
|
||||||
|
|
||||||
|
|
||||||
|
List<Component> mlist = Modifiers.getUniqueModifierList(lvl, modifierCategory, modifierIdentifiers);
|
||||||
|
for (Component mc : mlist) {
|
||||||
|
LabelElement<?> mcl = new LabelElement<>(
|
||||||
|
Spatials.positionXY(labelX, labelY).width(this.innerWidth() - labelX).height(15),
|
||||||
|
mc, LabelTextStyle.defaultStyle());
|
||||||
|
this.addElement(mcl);
|
||||||
|
labelY += 10;
|
||||||
|
}
|
||||||
|
this.addElement(new NineSliceElement<>(
|
||||||
|
Spatials.positionXY(0, labelY).width(this.innerWidth()).height(3),
|
||||||
|
ScreenTextures.BUTTON_EMPTY));
|
||||||
|
labelY += 10;
|
||||||
|
}
|
||||||
|
if (Config.DEBUG_UNIQUE_GEAR.get()) {
|
||||||
|
var badEntries = uniqueRegistry.entrySet().stream().filter(entry -> entry.getValue().getModel() == null || !entry.getValue().getModel().toString().contains(regPath)).toList();
|
||||||
|
this.addElement(new LabelElement<>(
|
||||||
|
Spatials.positionXY(labelX, labelY).width(this.innerWidth() - labelX).height(15),
|
||||||
|
new TextComponent("[DEBUG] BAD ENTRIES:").withStyle(ChatFormatting.RED), LabelTextStyle.defaultStyle()));
|
||||||
|
labelY += 10;
|
||||||
|
for (Map.Entry<ResourceLocation, UniqueGearConfig.Entry> entry : badEntries) {
|
||||||
|
this.addElement(new LabelElement<>(
|
||||||
|
Spatials.positionXY(labelX, labelY).width(this.innerWidth() - labelX).height(15),
|
||||||
|
new TextComponent("ID: " + entry.getKey().toString()).withStyle(ChatFormatting.RED),
|
||||||
|
LabelTextStyle.defaultStyle()));
|
||||||
|
labelY += 10;
|
||||||
|
UniqueGearConfig.Entry value = entry.getValue();
|
||||||
|
if (value == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
this.addElement(new LabelElement<>(
|
||||||
|
Spatials.positionXY(labelX, labelY).width(this.innerWidth() - labelX).height(15),
|
||||||
|
new TextComponent("Model: " + value.getModel()).withStyle(ChatFormatting.RED),
|
||||||
|
LabelTextStyle.defaultStyle()));
|
||||||
|
labelY += 16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getScroll() {
|
||||||
|
return this.verticalScrollBarElement.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setScroll(float scroll) {
|
||||||
|
this.verticalScrollBarElement.setValue(scroll);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InnerGearScreen create(ISpatial spatial, int lvl, ModifierCategory modifierCategory, ItemStack gearPiece) {
|
||||||
|
return new UniqueGearListContainer(spatial, lvl, modifierCategory, gearPiece);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
{
|
{
|
||||||
"vhatcaniroll.screen.title": "Gear Modifiers",
|
"vhatcaniroll.screen.title.random": "Random Modifiers",
|
||||||
|
"vhatcaniroll.screen.title.crafted": "Crafted Modifiers",
|
||||||
|
"vhatcaniroll.screen.title.unique": "Unique Gear",
|
||||||
|
"vhatcaniroll.screen.title.transmogs": "Transmogs",
|
||||||
"vhatcaniroll.openmodscreen": "Open VHat can I roll? screen",
|
"vhatcaniroll.openmodscreen": "Open VHat can I roll? screen",
|
||||||
"key.categories.vhatcaniroll": "VHat can I roll?"
|
"key.categories.vhatcaniroll": "VHat can I roll?"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,11 +5,13 @@
|
||||||
"compatibilityLevel": "JAVA_8",
|
"compatibilityLevel": "JAVA_8",
|
||||||
"refmap": "vhatcaniroll.refmap.json",
|
"refmap": "vhatcaniroll.refmap.json",
|
||||||
"mixins": [
|
"mixins": [
|
||||||
"EffectConfigAccessor"
|
|
||||||
],
|
],
|
||||||
"client": [
|
"client": [
|
||||||
|
"EffectConfigAccessor",
|
||||||
"StatisticsElementContainerScreenMixin",
|
"StatisticsElementContainerScreenMixin",
|
||||||
"VaultGearTierConfigAccessor"
|
"UniqueGearConfigAccessor",
|
||||||
|
"VaultGearTierConfigAccessor",
|
||||||
|
"AbilityFloatValueAttributeReaderInvoker"
|
||||||
],
|
],
|
||||||
"injectors": {
|
"injectors": {
|
||||||
"defaultRequire": 1
|
"defaultRequire": 1
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue