diff options
Diffstat (limited to 'src/main/java')
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) + ).let { Renderable.hoverable(hovered = Renderable.underlined(it), unhovered = it) }, + onClick = { + config::enabled.jumpToEditor() + reset() + WardrobeAPI.currentPage = null + } + ), + blockBottomHover = false + ), + config.color.backgroundColor.toChromaColor(), + padding = borderPadding + ) + + private fun reset() { + WardrobeAPI.inCustomWardrobe = false + editMode = false + displayRenderable = null + inventoryButton = null + } + + private fun addButtons(): Renderable { + val (horizontalSpacing, verticalSpacing) = with(config.spacing) { + buttonHorizontalSpacing.get() * (activeScale / 100.0) to buttonVerticalSpacing.get() * (activeScale / 100.0) + } + + val backButton = createLabeledButton( + "§aBack", + onClick = { + InventoryUtils.clickSlot(48) + reset() + WardrobeAPI.currentPage = null + } + ) + val exitButton = createLabeledButton( + "§cClose", + onClick = { + InventoryUtils.clickSlot(49) + reset() + WardrobeAPI.currentPage = null |
