summaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
authorEmpa <42304516+ItsEmpa@users.noreply.github.com>2024-06-09 19:41:41 +0200
committerGitHub <noreply@github.com>2024-06-09 19:41:41 +0200
commitcc629382945460d48fc9fa6472106df9fcbb589d (patch)
tree64caa8a0cee2d321f700b7d97fb13754319f82d4 /src/main/java
parentfc8e81a9f88b01ec63d8fa1d7f0d6ebbdc51d836 (diff)
downloadskyhanni-cc629382945460d48fc9fa6472106df9fcbb589d.tar.gz
skyhanni-cc629382945460d48fc9fa6472106df9fcbb589d.tar.bz2
skyhanni-cc629382945460d48fc9fa6472106df9fcbb589d.zip
Feature: Custom Wardrobe (#2039)
Co-authored-by: J10a1n15 <45315647+j10a1n15@users.noreply.github.com> Co-authored-by: Cal <cwolfson58@gmail.com> Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com>
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/inventory/InventoryConfig.java27
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/inventory/customwardrobe/ColorConfig.java44
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/inventory/customwardrobe/CustomWardrobeConfig.java54
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/inventory/customwardrobe/SpacingConfig.java145
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java15
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/inventory/wardrobe/CustomWardrobe.kt595
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/inventory/wardrobe/EstimatedWardrobePrice.kt41
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/inventory/wardrobe/WardrobeAPI.kt207
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/inventory/wardrobe/WardrobeSlot.kt42
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/misc/items/EstimatedWardrobePrice.kt74
-rw-r--r--src/main/java/at/hannibal2/skyhanni/mixins/hooks/GuiContainerHook.kt5
-rw-r--r--src/main/java/at/hannibal2/skyhanni/mixins/transformers/gui/AccessorGuiContainer.java6
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/ColorUtils.kt18
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/EntityUtils.kt24
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/InventoryUtils.kt10
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/ItemUtils.kt7
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/RenderUtils.kt17
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/renderables/Renderable.kt115
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/renderables/RenderableTooltips.kt2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/renderables/RenderableUtils.kt9
20 files changed, 1348 insertions, 109 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/inventory/InventoryConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/InventoryConfig.java
index 05f701059..f20643cc3 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/inventory/InventoryConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/InventoryConfig.java
@@ -3,6 +3,7 @@ package at.hannibal2.skyhanni.config.features.inventory;
import at.hannibal2.skyhanni.config.FeatureToggle;
import at.hannibal2.skyhanni.config.HasLegacyId;
import at.hannibal2.skyhanni.config.features.inventory.chocolatefactory.ChocolateFactoryConfig;
+import at.hannibal2.skyhanni.config.features.inventory.customwardrobe.CustomWardrobeConfig;
import at.hannibal2.skyhanni.config.features.inventory.helper.HelperConfig;
import at.hannibal2.skyhanni.config.features.itemability.ItemAbilityConfig;
import at.hannibal2.skyhanni.config.features.misc.EstimatedItemValueConfig;
@@ -50,6 +51,10 @@ public class InventoryConfig {
public ItemAbilityConfig itemAbilities = new ItemAbilityConfig();
@Expose
+ @Category(name = "Custom Wardrobe", desc = "New Wardrobe Look.")
+ public CustomWardrobeConfig customWardrobe = new CustomWardrobeConfig();
+
+ @Expose
@Category(name = "Chocolate Factory", desc = "Features to help you master the Chocolate Factory idle game.")
public ChocolateFactoryConfig chocolateFactory = new ChocolateFactoryConfig();
@@ -93,16 +98,13 @@ public class InventoryConfig {
@Accordion
public GetFromSackConfig gfs = new GetFromSackConfig();
+ @Expose
@ConfigOption(name = "Pocket Sack-In-A-Sack", desc = "")
@Accordion
- @Expose
public PocketSackInASackConfig pocketSackInASack = new PocketSackInASackConfig();
@Expose
- @ConfigOption(
- name = "Item Number",
- desc = "Showing the item number as a stack size for these items."
- )
+ @ConfigOption(name = "Item Number", desc = "Showing the item number as a stack size for these items.")
@ConfigEditorDraggableList
public List<ItemNumberEntry> itemNumberAsStackSize = new ArrayList<>(Arrays.asList(
NEW_YEAR_CAKE,
@@ -168,10 +170,10 @@ public class InventoryConfig {
public boolean vacuumBagCap = true;
@Expose
- @ConfigOption(
- name = "Quick Craft Confirmation",
+ @ConfigOption(name = "Quick Craft Confirmation",
desc = "Require Ctrl+Click to craft items that aren't often quick crafted " +
- "(e.g. armor, weapons, accessories). Sack items can be crafted normally."
+ "(e.g. armor, weapons, accessories). " +
+ "Sack items can be crafted normally."
)
@ConfigEditorBoolean
@FeatureToggle
@@ -190,23 +192,20 @@ public class InventoryConfig {
public boolean anvilCombineHelper = false;
@Expose
- @ConfigOption(name = "Item Stars",
- desc = "Show a compact star count in the item name for all items.")
+ @ConfigOption(name = "Item Stars", desc = "Show a compact star count in the item name for all items.")
@ConfigEditorBoolean
@FeatureToggle
public boolean itemStars = false;
@Expose
- @ConfigOption(name = "Missing Tasks",
- desc = "Highlight missing tasks in the SkyBlock Level Guide inventory.")
+ @ConfigOption(name = "Missing Tasks", desc = "Highlight missing tasks in the SkyBlock Level Guide inventory.")
// TODO move( , "inventory.highlightMissingSkyBlockLevelGuide", "inventory.skyblockGuideConfig.highlightMissingSkyBlockLevelGuide")
@ConfigEditorBoolean
@FeatureToggle
public boolean highlightMissingSkyBlockLevelGuide = true;
@Expose
- @ConfigOption(name = "Power Stone Guide",
- desc = "Highlight missing power stones, show their total bazaar price, and allows to open the bazaar when clicking on the items in the Power Stone Guide.")
+ @ConfigOption(name = "Power Stone Guide", desc = "Highlight missing power stones, show their total bazaar price, and allows to open the bazaar when clicking on the items in the Power Stone Guide.")
// TODO move( , "inventory.powerStoneGuide", "inventory.skyblockGuideConfig.powerStoneGuide")
@ConfigEditorBoolean
@FeatureToggle
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/inventory/customwardrobe/ColorConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/customwardrobe/ColorConfig.java
new file mode 100644
index 000000000..20f928254
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/customwardrobe/ColorConfig.java
@@ -0,0 +1,44 @@
+package at.hannibal2.skyhanni.config.features.inventory.customwardrobe;
+
+import com.google.gson.annotations.Expose;
+import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorColour;
+import io.github.notenoughupdates.moulconfig.annotations.ConfigOption;
+
+public class ColorConfig {
+
+ @Expose
+ @ConfigOption(name = "Background", desc = "Color of the GUI background.")
+ @ConfigEditorColour
+ public String backgroundColor = "0:127:0:0:0";
+
+ @Expose
+ @ConfigOption(name = "Equipped", desc = "Color of the currently equipped wardrobe slot.")
+ @ConfigEditorColour
+ public String equippedColor = "0:127:85:255:85";
+
+ @Expose
+ @ConfigOption(name = "Favorite", desc = "Color of the wardrobe slots that have been added as favorites.")
+ @ConfigEditorColour
+ public String favoriteColor = "0:127:255:85:85";
+
+ @Expose
+ @ConfigOption(name = "Same Page", desc = "Color of wardrobe slots in the same page.")
+ @ConfigEditorColour
+ public String samePageColor = "0:127:94:108:255";
+
+ @Expose
+ @ConfigOption(name = "Other Page", desc = "Color of wardrobe slots in another page.")
+ @ConfigEditorColour
+ public String otherPageColor = "0:127:0:0:0";
+
+ @Expose
+ @ConfigOption(name = "Top Outline", desc = "Color of the top of the outline when hovered.")
+ @ConfigEditorColour
+ public String topBorderColor = "0:255:255:200:0";
+
+ @Expose
+ @ConfigOption(name = "Bottom Outline", desc = "Color of the bottom of the outline when hovered.")
+ @ConfigEditorColour
+ public String bottomBorderColor = "0:255:255:0:0";
+
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/inventory/customwardrobe/CustomWardrobeConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/customwardrobe/CustomWardrobeConfig.java
new file mode 100644
index 000000000..a4ea69bad
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/customwardrobe/CustomWardrobeConfig.java
@@ -0,0 +1,54 @@
+package at.hannibal2.skyhanni.config.features.inventory.customwardrobe;
+
+import at.hannibal2.skyhanni.config.FeatureToggle;
+import com.google.gson.annotations.Expose;
+import io.github.notenoughupdates.moulconfig.annotations.Accordion;
+import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorBoolean;
+import io.github.notenoughupdates.moulconfig.annotations.ConfigOption;
+
+public class CustomWardrobeConfig {
+
+ @Expose
+ @ConfigOption(name = "Enable", desc = "Enables the Custom Wardrobe GUI.")
+ @ConfigEditorBoolean
+ @FeatureToggle
+ public boolean enabled = true;
+
+ @Expose
+ @ConfigOption(name = "Follow mouse", desc = "Players follow the movement of the mouse.")
+ @ConfigEditorBoolean
+ public boolean eyesFollowMouse = true;
+
+ @Expose
+ @ConfigOption(name = "Hide Empty Slots", desc = "Hides wardrobe slots with no armor.")
+ @ConfigEditorBoolean
+ public boolean hideEmptySlots = false;
+
+ @Expose
+ @ConfigOption(name = "Hide Locked Slots", desc = "Hides locked wardrobe slots.")
+ @ConfigEditorBoolean
+ public boolean hideLockedSlots = false;
+
+ @Expose
+ public boolean onlyFavorites = false;
+
+ @Expose
+ @ConfigOption(name = "Estimated Value", desc = "Show a §2$ §7sign you can hover to see the wardrobe slot value.")
+ @ConfigEditorBoolean
+ public boolean estimatedValue = true;
+
+ @Expose
+ @ConfigOption(name = "Loading text", desc = "Shows a \"§cLoading...\" §7text when the wardrobe page hasn't fully loaded in yet.")
+ @ConfigEditorBoolean
+ public boolean loadingText = true;
+
+ @Expose
+ @ConfigOption(name = "Colors", desc = "Change the color settings.")
+ @Accordion
+ public ColorConfig color = new ColorConfig();
+
+ @Expose
+ @ConfigOption(name = "Spacing", desc = "")
+ @Accordion
+ public SpacingConfig spacing = new SpacingConfig();
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/inventory/customwardrobe/SpacingConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/customwardrobe/SpacingConfig.java
new file mode 100644
index 000000000..363a9a6a7
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/customwardrobe/SpacingConfig.java
@@ -0,0 +1,145 @@
+package at.hannibal2.skyhanni.config.features.inventory.customwardrobe;
+
+import com.google.gson.annotations.Expose;
+import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorSlider;
+import io.github.notenoughupdates.moulconfig.annotations.ConfigOption;
+import io.github.notenoughupdates.moulconfig.observer.Property;
+
+public class SpacingConfig {
+
+ @Expose
+ @ConfigOption(name = "Global Scale", desc = "Controls the scale of the entirety of the wardrobe.")
+ @ConfigEditorSlider(
+ minValue = 30,
+ maxValue = 200,
+ minStep = 1
+ )
+ public Property<Integer> globalScale = Property.of(100);
+
+ @Expose
+ @ConfigOption(name = "Outline Thickness", desc = "How thick the outline of the hovered slot is.")
+ @ConfigEditorSlider(
+ minValue = 1,
+ maxValue = 15,
+ minStep = 1
+ )
+ public Property<Integer> outlineThickness = Property.of(5);
+
+ @Expose
+ @ConfigOption(name = "Outline Blur", desc = "Amount of blur of the outline.")
+ @ConfigEditorSlider(
+ minValue = 0f,
+ maxValue = 1f,
+ minStep = 0.1f
+ )
+ public Property<Float> outlineBlur = Property.of(0.5f);
+
+ @Expose
+ @ConfigOption(name = "Slot Width", desc = "Width of the wardrobe slots.")
+ @ConfigEditorSlider(
+ minValue = 30,
+ maxValue = 100,
+ minStep = 1
+ )
+ public Property<Integer> slotWidth = Property.of(75);
+
+ @Expose
+ @ConfigOption(name = "Slot Height", desc = "Height of the wardrobe slots.")
+ @ConfigEditorSlider(
+ minValue = 60,
+ maxValue = 200,
+ minStep = 1
+ )
+ public Property<Integer> slotHeight = Property.of(140);
+
+ @Expose
+ @ConfigOption(name = "Player Scale", desc = "Scale of the players.")
+ @ConfigEditorSlider(
+ minValue = 0,
+ maxValue = 100,
+ minStep = 1
+ )
+ public Property<Integer> playerScale = Property.of(75);
+
+ @Expose
+ @ConfigOption(name = "Slots per Row", desc = "Max amount of wardrobe slots per row.")
+ @ConfigEditorSlider(
+ minValue = 5,
+ maxValue = 18,
+ minStep = 1
+ )
+ public Property<Integer> maxPlayersPerRow = Property.of(9);
+
+ @Expose
+ @ConfigOption(name = "Slots Horizontal Spacing", desc = "How much space horizontally between wardrobe slots.")
+ @ConfigEditorSlider(
+ minValue = 1,
+ maxValue = 20,
+ minStep = 1
+ )
+ public Property<Integer> horizontalSpacing = Property.of(3);
+
+ @Expose
+ @ConfigOption(name = "Slots Vertical Spacing", desc = "How much space vertically between wardrobe slots.")
+ @ConfigEditorSlider(
+ minValue = 1,
+ maxValue = 20,
+ minStep = 1
+ )
+ public Property<Integer> verticalSpacing = Property.of(3);
+
+ @Expose
+ @ConfigOption(name = "Slots & Buttons Spacing", desc = "How much vertical space there is between wardrobe slots and the buttons.")
+ @ConfigEditorSlider(
+ minValue = 1,
+ maxValue = 40,
+ minStep = 1
+ )
+ public Property<Integer> buttonSlotsVerticalSpacing = Property.of(10);
+
+ @Expose
+ @ConfigOption(name = "Button Horizontal Spacing", desc = "How much space horizontally between buttons.")
+ @ConfigEditorSlider(
+ minValue = 1,
+ maxValue = 40,
+ minStep = 1
+ )
+ public Property<Integer> buttonHorizontalSpacing = Property.of(10);
+
+ @Expose
+ @ConfigOption(name = "Button Vertical Spacing", desc = "How much space vertically between buttons.")
+ @ConfigEditorSlider(
+ minValue = 1,
+ maxValue = 40,
+ minStep = 1
+ )
+ public Property<Integer> buttonVerticalSpacing = Property.of(10);
+
+ @Expose
+ @ConfigOption(name = "Button Width", desc = "Width of the buttons.")
+ @ConfigEditorSlider(
+ minValue = 1,
+ maxValue = 60,
+ minStep = 1
+ )
+ public Property<Integer> buttonWidth = Property.of(50);
+
+ @Expose
+ @ConfigOption(name = "Button Height", desc = "Height of the buttons.")
+ @ConfigEditorSlider(
+ minValue = 1,
+ maxValue = 60,
+ minStep = 1
+ )
+ public Property<Integer> buttonHeight = Property.of(20);
+
+ @Expose
+ @ConfigOption(name = "Background Padding", desc = "Space between the edges of the background and the slots.")
+ @ConfigEditorSlider(
+ minValue = 1,
+ maxValue = 20,
+ minStep = 1
+ )
+ public Property<Integer> backgroundPadding = Property.of(10);
+
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java b/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java
index 9d0ca44f9..e037b80a6 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/storage/ProfileSpecificStorage.java
@@ -28,6 +28,7 @@ import at.hannibal2.skyhanni.features.garden.fortuneguide.FarmingItems;
import at.hannibal2.skyhanni.features.garden.pests.PestProfitTracker;
import at.hannibal2.skyhanni.features.garden.pests.VinylType;
import at.hannibal2.skyhanni.features.garden.visitor.VisitorReward;
+import at.hannibal2.skyhanni.features.inventory.wardrobe.WardrobeAPI;
import at.hannibal2.skyhanni.features.mining.fossilexcavator.ExcavatorProfitTracker;
import at.hannibal2.skyhanni.features.mining.powdertracker.PowderTracker;
import at.hannibal2.skyhanni.features.misc.trevor.TrevorTracker;
@@ -618,7 +619,7 @@ public class ProfileSpecificStorage {
public DianaProfitTracker.Data dianaProfitTracker = new DianaProfitTracker.Data();
@Expose
- // TODO renmae
+ // TODO rename
public MythologicalCreatureTracker.Data mythologicalMobTracker = new MythologicalCreatureTracker.Data();
}
@@ -626,5 +627,17 @@ public class ProfileSpecificStorage {
public Map<SkillType, SkillAPI.SkillInfo> skillData = new HashMap<>();
@Expose
+ public WardrobeStorage wardrobe = new WardrobeStorage();
+
+ public static class WardrobeStorage {
+ @Expose
+ public Map<Integer, WardrobeAPI.WardrobeData> data = new HashMap<>();
+
+ @Expose
+ @Nullable
+ public Integer currentSlot = null;
+ }
+
+ @Expose
public UpgradeReminder.CommunityShopUpgrade communityShopProfileUpgrade = null;
}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/wardrobe/CustomWardrobe.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/wardrobe/CustomWardrobe.kt
new file mode 100644
index 000000000..243b3132f
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/wardrobe/CustomWardrobe.kt
@@ -0,0 +1,595 @@
+package at.hannibal2.skyhanni.features.inventory.wardrobe
+
+import at.hannibal2.skyhanni.SkyHanniMod
+import at.hannibal2.skyhanni.config.core.config.Position
+import at.hannibal2.skyhanni.events.ConfigLoadEvent
+import at.hannibal2.skyhanni.events.GuiContainerEvent
+import at.hannibal2.skyhanni.events.GuiRenderEvent
+import at.hannibal2.skyhanni.events.InventoryCloseEvent
+import at.hannibal2.skyhanni.events.InventoryUpdatedEvent
+import at.hannibal2.skyhanni.features.inventory.wardrobe.WardrobeAPI.MAX_PAGES
+import at.hannibal2.skyhanni.features.inventory.wardrobe.WardrobeAPI.MAX_SLOT_PER_PAGE
+import at.hannibal2.skyhanni.mixins.transformers.gui.AccessorGuiContainer
+import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule
+import at.hannibal2.skyhanni.utils.ColorUtils.addAlpha
+import at.hannibal2.skyhanni.utils.ColorUtils.darker
+import at.hannibal2.skyhanni.utils.ColorUtils.toChromaColor
+import at.hannibal2.skyhanni.utils.ColorUtils.toChromaColorInt
+import at.hannibal2.skyhanni.utils.ColorUtils.withAlpha
+import at.hannibal2.skyhanni.utils.ConditionalUtils
+import at.hannibal2.skyhanni.utils.ConditionalUtils.transformIf
+import at.hannibal2.skyhanni.utils.ConfigUtils.jumpToEditor
+import at.hannibal2.skyhanni.utils.DelayedRun
+import at.hannibal2.skyhanni.utils.EntityUtils.getFakePlayer
+import at.hannibal2.skyhanni.utils.InventoryUtils
+import at.hannibal2.skyhanni.utils.ItemUtils.removeEnchants
+import at.hannibal2.skyhanni.utils.LorenzUtils
+import at.hannibal2.skyhanni.utils.RenderUtils.HorizontalAlignment
+import at.hannibal2.skyhanni.utils.RenderUtils.VerticalAlignment
+import at.hannibal2.skyhanni.utils.RenderUtils.renderRenderable
+import at.hannibal2.skyhanni.utils.renderables.Renderable
+import net.minecraft.client.Minecraft
+import net.minecraft.client.gui.inventory.GuiContainer
+import net.minecraft.client.renderer.GlStateManager
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import java.awt.Color
+import kotlin.math.min
+import kotlin.time.Duration.Companion.milliseconds
+
+@SkyHanniModule
+object CustomWardrobe {
+
+ val config get() = SkyHanniMod.feature.inventory.customWardrobe
+
+ private var displayRenderable: Renderable? = null
+ private var inventoryButton: Renderable? = null
+ private var editMode = false
+ private var waitingForInventoryUpdate = false
+
+ private var activeScale: Int = 100
+ private var currentMaxSize: Pair<Int, Int>? = null
+ private var lastScreenSize: Pair<Int, Int>? = null
+ private var guiName = "Custom Wardrobe"
+
+ @SubscribeEvent
+ fun onGuiRender(event: GuiContainerEvent.BeforeDraw) {
+ if (!isEnabled() || editMode) return
+ val renderable = displayRenderable ?: run {
+ update()
+ displayRenderable ?: return
+ }
+
+ val gui = event.gui
+ val screenSize = gui.width to gui.height
+
+ if (screenSize != lastScreenSize) {
+ lastScreenSize = screenSize
+ val shouldUpdate = updateScreenSize(screenSize)
+ if (shouldUpdate) {
+ update()
+ return
+ }
+ }
+
+ val (width, height) = renderable.width to renderable.height
+ val pos = Position((gui.width - width) / 2, (gui.height - height) / 2)
+ if (waitingForInventoryUpdate && config.loadingText) {
+ val loadingRenderable = Renderable.string(
+ "§cLoading...",
+ scale = activeScale / 100.0
+ )
+ val loadingPos =
+ Position(pos.rawX + (width - loadingRenderable.width) / 2, pos.rawY - loadingRenderable.height)
+ loadingPos.renderRenderable(loadingRenderable, posLabel = guiName, addToGuiManager = false)
+ }
+
+ GlStateManager.translate(0f, 0f, 100f)
+ pos.renderRenderable(renderable, posLabel = guiName, addToGuiManager = false)
+ GlStateManager.translate(0f, 0f, -100f)
+ event.cancel()
+ }
+
+ // Edit button in normal wardrobe while in edit mode
+ @SubscribeEvent
+ fun onRenderOverlay(event: GuiRenderEvent.ChestGuiOverlayRenderEvent) {
+ if (!isEnabled()) return
+ if (!editMode) return
+ val gui = Minecraft.getMinecraft().currentScreen as? GuiContainer ?: return
+ val renderable = inventoryButton ?: addReEnableButton().also { inventoryButton = it }
+ val accessorGui = gui as AccessorGuiContainer
+ val posX = accessorGui.guiLeft + (1.05 * accessorGui.width).toInt()
+ val posY = accessorGui.guiTop + (accessorGui.height - renderable.height) / 2
+ Position(posX, posY).renderRenderable(renderable, posLabel = guiName, addToGuiManager = false)
+ }
+
+ @SubscribeEvent
+ fun onInventoryClose(event: InventoryCloseEvent) {
+ waitingForInventoryUpdate = false
+ if (!isEnabled()) return
+ DelayedRun.runDelayed(250.milliseconds) {
+ if (!WardrobeAPI.inWardrobe()) {
+ reset()
+ }
+ }
+ }
+
+ @SubscribeEvent
+ fun onConfigUpdate(event: ConfigLoadEvent) {
+ with(config.spacing) {
+ ConditionalUtils.onToggle(
+ globalScale, outlineThickness, outlineBlur,
+ slotWidth, slotHeight, playerScale,
+ maxPlayersPerRow, horizontalSpacing, verticalSpacing,
+ buttonSlotsVerticalSpacing, buttonHorizontalSpacing, buttonVerticalSpacing,
+ buttonWidth, buttonHeight, backgroundPadding,
+ ) {
+ currentMaxSize = null
+ lastScreenSize = null
+ }
+ }
+ }
+
+ @SubscribeEvent
+ fun onInventoryUpdate(event: InventoryUpdatedEvent) {
+ if (!isEnabled() || editMode) return
+ update()
+ }
+
+ private fun update() {
+ displayRenderable = createRenderables()
+ }
+
+ private fun updateScreenSize(gui: Pair<Int, Int>): Boolean {
+ val renderable = currentMaxSize ?: run {
+ activeScale = config.spacing.globalScale.get()
+ update()
+ return true
+ }
+ val previousActiveScale = activeScale
+ val unscaledRenderableWidth = renderable.first / activeScale
+ val unscaledRenderableHeight = renderable.second / activeScale
+ val autoScaleWidth = 0.95 * gui.first / unscaledRenderableWidth
+ val autoScaleHeight = 0.95 * gui.second / unscaledRenderableHeight
+ val maxScale = min(autoScaleWidth, autoScaleHeight).toInt()
+
+ activeScale = config.spacing.globalScale.get().coerceAtMost(maxScale)
+
+ return activeScale != previousActiveScale
+ }
+
+ private fun createWarning(list: List<WardrobeSlot>): Pair<String?, List<WardrobeSlot>> {
+ var wardrobeWarning: String? = null
+ var wardrobeSlots = list
+
+ if (wardrobeSlots.isEmpty()) wardrobeWarning = "§cYour wardrobe is empty :("
+
+ if (config.hideLockedSlots) {
+ wardrobeSlots = wardrobeSlots.filter { !it.locked }
+ if (wardrobeSlots.isEmpty()) wardrobeWarning = "§cAll your slots are locked? Somehow"
+ }
+
+ if (config.hideEmptySlots) {
+ wardrobeSlots = wardrobeSlots.filter { !it.isEmpty() }
+ if (wardrobeSlots.isEmpty()) wardrobeWarning = "§cAll slots are empty :("
+ }
+ if (config.onlyFavorites) {
+ wardrobeSlots = wardrobeSlots.filter { it.favorite || it.isCurrentSlot() }
+ if (wardrobeSlots.isEmpty()) wardrobeWarning = "§cDidn't set any favorites"
+ }
+
+ return wardrobeWarning to wardrobeSlots
+ }
+
+ private fun createArmorTooltipRenderable(
+ slot: WardrobeSlot,
+ containerHeight: Int,
+ containerWidth: Int,
+ ): Renderable {
+ val loreList = mutableListOf<Renderable>()
+ val height = containerHeight - 3
+
+ // This is needed to keep the background size the same as the player renderable size
+ val hoverableSizes = MutableList(4) { height / 4 }.apply {
+ for (k in 0 until height % 4) this[k]++
+ }
+
+ for (armorIndex in 0 until 4) {
+ val stack = slot.armor[armorIndex]?.copy()
+ if (stack == null) {
+ loreList.add(Renderable.placeholder(containerWidth, hoverableSizes[armorIndex]))
+ } else {
+ loreList.add(
+ Renderable.hoverable(
+ Renderable.hoverTips(
+ Renderable.placeholder(containerWidth, hoverableSizes[armorIndex]),
+ stack.getTooltip(Minecraft.getMinecraft().thePlayer, false)
+ ),
+ Renderable.placeholder(containerWidth, hoverableSizes[armorIndex]),
+ bypassChecks = true
+ )
+ )
+ }
+ }
+ return Renderable.verticalContainer(loreList, spacing = 1)
+ }
+
+ private fun createFakePlayerRenderable(
+ slot: WardrobeSlot,
+ playerWidth: Double,
+ containerHeight: Int,
+ containerWidth: Int,
+ ): Renderable {
+ val fakePlayer = getFakePlayer()
+ var scale = playerWidth
+
+ fakePlayer.inventory.armorInventory =
+ slot.armor.map { it?.copy()?.removeEnchants() }.reversed().toTypedArray()
+
+ val playerColor = if (!slot.isInCurrentPage()) {
+ scale *= 0.9
+ Color.GRAY.withAlpha(100)
+ } else null
+
+ return Renderable.fakePlayer(
+ fakePlayer,
+ followMouse = config.eyesFollowMouse,
+ width = containerWidth,
+ height = containerHeight,
+ entityScale = scale.toInt(),
+ padding = 0,
+ color = playerColor,
+ )
+ }
+
+ private fun createRenderables(): Renderable {
+ val (wardrobeWarning, list) = createWarning(WardrobeAPI.slots)
+
+ val maxPlayersPerRow = config.spacing.maxPlayersPerRow.get().coerceAtLeast(1)
+ val maxPlayersRows = ((MAX_SLOT_PER_PAGE * MAX_PAGES - 1) / maxPlayersPerRow) + 1
+ val containerWidth = (config.spacing.slotWidth.get() * (activeScale / 100.0)).toInt()
+ val containerHeight = (config.spacing.slotHeight.get() * (activeScale / 100.0)).toInt()
+ val playerWidth = (containerWidth * (config.spacing.playerScale.get() / 100.0))
+ val horizontalSpacing = (config.spacing.horizontalSpacing.get() * (activeScale / 100.0)).toInt()
+ val verticalSpacing = (config.spacing.verticalSpacing.get() * (activeScale / 100.0)).toInt()
+ val backgroundPadding = (config.spacing.backgroundPadding.get() * (activeScale / 100.0)).toInt()
+ val buttonVerticalSpacing = (config.spacing.buttonVerticalSpacing.get() * (activeScale / 100.0)).toInt()
+
+ var maxRenderableWidth = maxPlayersPerRow * containerWidth + (maxPlayersPerRow - 1) * horizontalSpacing
+ var maxRenderableHeight = maxPlayersRows * containerHeight + (maxPlayersRows - 1) * verticalSpacing
+
+ val button = addButtons()
+
+ if (button.width > maxRenderableWidth) maxRenderableWidth = button.width
+ maxRenderableHeight += button.height + buttonVerticalSpacing
+
+ maxRenderableWidth += 2 * backgroundPadding
+ maxRenderableHeight += 2 * backgroundPadding
+ currentMaxSize = maxRenderableWidth to maxRenderableHeight
+
+ wardrobeWarning?.let { text ->
+ val warningRenderable = Renderable.wrappedString(
+ text,
+ maxRenderableWidth,
+ 3.0 * (activeScale / 100.0),
+ horizontalAlign = HorizontalAlignment.CENTER
+ )
+ val withButtons = Renderable.verticalContainer(
+ listOf(warningRenderable, button),
+ buttonVerticalSpacing,
+ horizontalAlign = HorizontalAlignment.CENTER
+ )
+ return addGuiBackground(withButtons, backgroundPadding)
+ }
+
+ val chunkedList = list.chunked(maxPlayersPerRow)
+
+ val rowsRenderables = chunkedList.map { row ->
+ val slotsRenderables = row.map { slot ->
+ val armorTooltipRenderable = createArmorTooltipRenderable(slot, containerHeight, containerWidth)
+
+ val playerBackground = createHoverableRenderable(
+ armorTooltipRenderable,
+ topLayerRenderable = addSlotHoverableButtons(slot),
+ hoveredColor = slot.getSlotColor(),
+ borderOutlineThickness = config.spacing.outlineThickness.get(),
+ borderOutlineBlur = config.spacing.outlineBlur.get(),
+ onClick = { slot.clickSlot() }
+ )
+
+ val playerRenderable = createFakePlayerRenderable(slot, playerWidth, containerHeight, containerWidth)
+
+ Renderable.doubleLayered(playerBackground, playerRenderable, false)
+ }
+ Renderable.horizontalContainer(slotsRenderables, horizontalSpacing)
+ }
+
+ val allSlotsRenderable = Renderable.verticalContainer(
+ rowsRenderables,
+ verticalSpacing,
+ horizontalAlign = HorizontalAlignment.CENTER
+ )
+
+ val withButtons = Renderable.verticalContainer(
+ listOf(allSlotsRenderable, button),
+ buttonVerticalSpacing,
+ horizontalAlign = HorizontalAlignment.CENTER
+ )
+
+ return addGuiBackground(withButtons, backgroundPadding)
+ }
+
+ private fun addGuiBackground(renderable: Renderable, borderPadding: Int) =
+ Renderable.drawInsideRoundedRect(
+ Renderable.doubleLayered(
+ renderable,
+ Renderable.clickable(
+ Renderable.string(
+ "§7SkyHanni",
+ horizontalAlign = HorizontalAlignment.RIGHT,
+ verticalAlign = VerticalAlignment.BOTTOM,
+ scale = 1.0 * (activeScale / 100.0)